游戏 黑白棋

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;
    }

猜你喜欢

转载自www.cnblogs.com/Tony-Double-Sky/p/9285526.html
今日推荐