游戏 黑白棋

jing shi给的灵感,一共是两天赶了5个小时做出来了,写完真的感觉代码力会提高不少

自己做的第一款游戏,但可能也是退役前最后一款了,目前还没测试出bug

鸣谢:

@附外赵日天 @浮生 (测试)

@niiick (修改查错)

更新日志

v2.5

  • 由于刷新率太慢,输入模式还原为坐标输入

  • 加入了存读档功能

  • 加入了退出游戏提前结算棋子数功能

  • 加入游戏结束动画

  • 修复了判断坐标合法RE的bug

  • 修复了边缘坐标始终合法的bug

v2.0

  • 更换输入坐标模式,利用wasd控制坐标输入

  • 加入开头动画

v1.0

  • 修复了吃棋过多的bug

  • 加入游戏小标题

v0.1

  • 初号机,制定了游戏大体框架

  • 递归的思想得到验证,确认算法核心

  • 若干bug等待调试

规则

如果玩家在棋盘上没有地方可以下子,则该玩家对手可以连下。双方都没有棋子可以下时棋局结束,以棋子数目来计算胜负,棋子多的一方获胜。
在棋盘还没有下满时,如果一方的棋子已经被对方吃光,则棋局也结束。将对手棋子吃光的一方获胜。
翻转棋类似于棋盘游戏“奥赛罗 (Othello)”,是一种得分会戏剧性变化并且需要长时间思考的策略性游戏。
翻转棋的棋盘上有 64 个可以放置黑白棋子的方格(类似于国际象棋和跳棋)。游戏的目标是使棋盘上自己颜色的棋子数超过对手的棋子数。
该游戏非常复杂,其名称就暗示着结果的好坏可能会迅速变化。
当游戏双方都不能再按规则落子时,游戏就结束了。通常,游戏结束时棋盘上会摆满了棋子。结束时谁的棋子最多谁就是赢家。

玩法

每个“翻转棋”游戏开始时,棋盘上已经交叉放好了四颗棋子。其中两颗是黑棋,另两颗是白棋。黑棋总是先走。
当您的棋子在某一直线方向包围了对手的棋子时,就可以翻转这些棋子的颜色,使它们成为您方的颜色。例如,如果您执黑棋,并且看到在一排白棋的某一端是一颗黑棋,那么当您将一颗黑棋放在这一排的另一端时,所有的白棋都将翻转并变为黑棋!
所有的直线方向均有效:水平、垂直和斜线方向。
走棋的唯一规则是只能走包围并翻转对手的棋子。每一回合都必须至少翻转一颗对手的棋子。
按规则不能再走棋时,这一回合弃权。这一步的行棋权将被交给对方。

核心原理

从8个方向增量数组出发,利用递归寻找同色棋,若找到则回溯,同时翻转路径上的所有棋子(位置合法判断方法大致相同)

Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <windows.h>
#include <ctime>
#include <conio.h>
#include <fstream>
using namespace std;
const int maxn = 19;
int now;
int map[maxn][maxn];
int out[maxn][maxn];
int can[maxn][maxn];
int mx[8] = {-1,0,1,-1,1,-1,0,1};
int my[8] = {-1,-1,-1,0,0,1,1,1};
void PTONY(){//Tony!!! 
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN);
}
void Pwhite(){//-1
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
} 
void Pred(){//1
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED);
}
void Pblue(){//0
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE);
}
void read(){
fstream File("save.txt",ios::in | ios::out);
int temp;
for(int i = 0;i <= 9;i++){
	for(int j = 0;j <= 9;j++){
		File>>temp;
		map[i][j] = temp;
		}
	}
for(int i = 0;i <= 9;i++){
	for(int j = 0;j <= 9;j++){
		File>>temp;
		out[i][j] = temp;
		}
	}
for(int i = 0;i <= 9;i++){
	for(int j = 0;j <= 9;j++){
		File>>temp;
		can[i][j] = temp;
		}
	}
File>>temp;
now = temp;
}
bool goon,end;
void start(){
PTONY();printf("Tony's mini Game\n");
Sleep(1000);
Pred(); 
printf("HOW TO PLAY\n");
Pwhite();
printf("输入坐标控制落子\n先纵轴 后横轴 以空格隔开\nEnter = 确定\n");
printf("坐标 0, 0结束游戏\n坐标19,19存档\n请在游玩时关闭输入法\n");
Sleep(1000);
PTONY();
printf("Tony Double Sky ");
Sleep(1000);
printf("Present\n");
Sleep(1000);
Pblue();
printf("thx:@Charles @niiick\n");
Pwhite();
printf("Press any key to continue");
char c = getch();
system("cls");
printf("请选择:\n1.读取存档\n2.新游戏\n");
char a = getch();
while(!(a == '1' || a == '2'))a = getch();
if(a == '1'){
	read();
	goon = 1;
	PTONY();
	printf("读档成功\n");
	Sleep(2000);
	}
}
void print(){
system("cls");
PTONY();printf(" Tony's mini Game\n");
Pwhite();
printf(" ");
for(int i = 1;i <= 8;i++)printf("%d ",i);
printf("\n");
for(int i = 1;i <= 8;i++){
	Pwhite();printf("%d",i);
	for(int j = 1;j <= 8;j++){
		if(out[i][j] == -1){
			Pwhite();printf("■");
			}
		else if(out[i][j] == 1){
			Pred();printf("■");
			}
		else{
			Pblue();printf("■");
			} 
		}
	printf("\n");
	}
if(now){Pred();printf("红方下\n");}
else{Pblue();printf("蓝方下\n");}
Pwhite();printf("请输入坐标\n");
}
void init(){
memset(map,-1,sizeof(map));
memset(out,-1,sizeof(out));
map[4][4] = out[4][4] = 1;
map[4][5] = out[4][5] = 0;
map[5][4] = out[5][4] = 0;
map[5][5] = out[5][5] = 1;
now = 1;
}
bool change(int x,int y,int mx,int my,int c){
if(map[x][y] == c)return 1;
if(map[x][y] == -1)return 0;
bool flag = change(x + mx,y + my,mx,my,c);
out[x][y] ^= flag;
return flag;
}
bool judge(int x,int y,int mx,int my,int c,bool flag){
if(map[x][y] == c)return (1 && flag);
if(map[x][y] == -1)return 0;
if(map[x][y] == c ^ 1)flag = 1;
return judge(x + mx,y + my,mx,my,c,flag);
}
bool check(int c){
memset(can,0,sizeof(can));
bool flag = 0;
for(int i = 1;i <= 8;i++){
	for(int j = 1;j <= 8;j++){
		if(map[i][j] == -1){
			for(int k = 0;k < 8;k++){
				int gox = mx[k];
				int goy = my[k];
				can[i][j] |= judge(i + gox,j + goy,gox,goy,c,0);
				if(can[i][j]){
					flag = 1;
					break;
					}
				}
			}
		}
	}
return flag;
}
void save(){
ofstream SaveFile("save.txt");
for(int i = 0;i <= 9;i++){
	for(int j = 0;j <= 9;j++){
		SaveFile<<map[i][j]<<" ";
		}
	SaveFile<<endl;
	}
for(int i = 0;i <= 9;i++){
	for(int j = 0;j <= 9;j++){
		SaveFile<<out[i][j]<<" ";
		}
	SaveFile<<endl;
	}
for(int i = 0;i <= 9;i++){
	for(int j = 0;j <= 9;j++){
		SaveFile<<can[i][j]<<" ";
		}
	SaveFile<<endl;
	}
SaveFile<<now<<endl;
SaveFile.close();
}
int main(){
	start();
	if(!goon)init();
	print();
	int cnt = 4;
	int x,y;
	bool again = 0;
	while(1){
		if(check(now)){
			scanf("%d%d",&x,&y);
			if(x == 19 && y == 19){
				save();
				PTONY();
				printf("已保存\n");
				Sleep(2000);
				print();
				continue;
				}
			else if(x == 0 && y == 0){
				break;
				}
			while(!can[x][y]){
				
				printf("位置不合法请重新输入:\n");
				scanf("%d%d",&x,&y);
				if(x == 19 && y == 19){
					save();
					PTONY();
					printf("已保存\n");
					Sleep(2000);
					print();
					continue;
					}
				else if(x == 0 && y == 0){
					end = 1;
					break;
					}
				}
			if(end)break;
			map[x][y] = now;cnt++;again = 0;
			for(int i = 0;i <= maxn;i++){
				for(int j = 0;j <= maxn;j++){
					out[i][j] = map[i][j];
					}
				}
			for(int k = 0;k < 8;k++){
				int gox = mx[k];
				int goy = my[k];
				change(x + gox,y + goy,gox,goy,now);
				}
			}
		else{
			if(now == 1)Pred(),printf("无棋可下\n");
			else Pblue(),printf("无棋可下\n");
			Sleep(2000);
			if(again)break;
			else again = 1;
			}
		now ^= 1;
		print();
		for(int i = 0;i <= maxn;i++){
			for(int j = 0;j <= maxn;j++){
				map[i][j] = out[i][j];
				}
			}
		}
	int R = 0,B = 0;
	for(int i = 1;i <= 8;i++){
		for(int j = 1;j <= 8;j++){
			if(map[i][j] == 1)R++;
			else if(map[i][j] == 0)B++;
			}
		}
	Pred();printf("红方得分:%d\n",R);
	Pblue();printf("蓝方得分:%d\n",B);
	Sleep(1000);
	if(R == B){
		Pwhite();printf("--平局--\n");
		}
	else if(R > B){
		Pred();printf("--红方胜--\n");
		}
	else{
		Pblue();printf("--蓝方胜--\n"); 
		}
	Sleep(2000);
	PTONY();printf("Thanks to play my game\n");
	Sleep(2000);
	printf("Press any key to end\n");
	char c = getch();
	return 0;
	}
posted @ 2018-07-09 19:15  Tony_Double_Sky  阅读(346)  评论(0编辑  收藏  举报