jing shi给的灵感,一共是两天赶了5个小时做出来了,写完真的感觉代码力会提高不少
自己做的第一款游戏,但可能也是退役前最后一款了,目前还没测试出bug
鸣谢:
@附外赵日天 @浮生 (测试)
@niiick (修改查错)
更新日志
v2.5
由于刷新率太慢,输入模式还原为坐标输入
加入了存读档功能
加入了退出游戏提前结算棋子数功能
加入游戏结束动画
修复了判断坐标合法RE的bug
修复了边缘坐标始终合法的bug
v2.0
更换输入坐标模式,利用wasd控制坐标输入
加入开头动画
v1.0
修复了吃棋过多的bug
加入游戏小标题
v0.1
初号机,制定了游戏大体框架
递归的思想得到验证,确认算法核心
若干bug等待调试
规则
如果玩家在棋盘上没有地方可以下子,则该玩家对手可以连下。双方都没有棋子可以下时棋局结束,以棋子数目来计算胜负,棋子多的一方获胜。
在棋盘还没有下满时,如果一方的棋子已经被对方吃光,则棋局也结束。将对手棋子吃光的一方获胜。 翻转棋类似于棋盘游戏“奥赛罗 (Othello)”,是一种得分会戏剧性变化并且需要长时间思考的策略性游戏。 翻转棋的棋盘上有 64 个可以放置黑白棋子的方格(类似于国际象棋和跳棋)。游戏的目标是使棋盘上自己颜色的棋子数超过对手的棋子数。 该游戏非常复杂,其名称就暗示着结果的好坏可能会迅速变化。 当游戏双方都不能再按规则落子时,游戏就结束了。通常,游戏结束时棋盘上会摆满了棋子。结束时谁的棋子最多谁就是赢家。玩法
每个“翻转棋”游戏开始时,棋盘上已经交叉放好了四颗棋子。其中两颗是黑棋,另两颗是白棋。黑棋总是先走。
当您的棋子在某一直线方向包围了对手的棋子时,就可以翻转这些棋子的颜色,使它们成为您方的颜色。例如,如果您执黑棋,并且看到在一排白棋的某一端是一颗黑棋,那么当您将一颗黑棋放在这一排的另一端时,所有的白棋都将翻转并变为黑棋! 所有的直线方向均有效:水平、垂直和斜线方向。 走棋的唯一规则是只能走包围并翻转对手的棋子。每一回合都必须至少翻转一颗对手的棋子。 按规则不能再走棋时,这一回合弃权。这一步的行棋权将被交给对方。核心原理
从8个方向增量数组出发,利用递归寻找同色棋,若找到则回溯,同时翻转路径上的所有棋子(位置合法判断方法大致相同)
Code
#include#include #include #include #include #include #include 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(){//-1SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);} void Pred(){//1SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED);}void Pblue(){//0SetConsoleTextAttribute(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<