IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 五子棋游戏 -> 正文阅读

[C++知识库]五子棋游戏

身为一个初学者,我认为代码是改出来的,非计算机专业大一的我学C语言不到一个月,用三天时间写出了一个很简单的五子棋玩家与电脑的对抗。刚学完数组,写完三子棋,只知道最简单的指针的我,秉承着技术不行代码来凑的方法,我用将近1500行的代码三天时间独立完成了这项工作没有任何参考和借鉴,虽然写的电脑玩家并不厉害,但与人博还是没有问题的,弈基本的交叉棋都可以判断。以下是我写代码时的一些思路和自己的想法。

目录

第一步编写界面

1.构思

2.功能的实现

第二步编写游戏内容

1.游戏的框架

2.功能的实现

第三步编写电脑玩家

1.分类

2.输出顺序

总结


第一步编写界面

1.构思

我们平时玩游戏并非打开它就直接开始游戏,打开游戏后最先印入眼帘的往往是游戏菜单,而菜单中必不可少的则是游戏的 ‘开始’ 与 ‘退出’ ,而开始与退出的简易界面我们设一个函数来处理

//菜单
void menu()
{
    printf("***********************************\n");
    printf("***********   1.Play   ************\n");
    printf("***********   0.Exit   ************\n");
    printf("***********************************\n");
}

这样我们就拥有了一个简易的菜单了!

2.功能的实现

有了菜单,接下来我们就要来实现菜单的功能 Play 和 Exit ,我在这里选择的是switch语句,switch(整型)恰好对应我们的1.Play和0.Exit,在这里我们需要思考,当玩家输入的不是1或0时,系统无法给出反馈,这时我们就要再给出一种情况default,使得在系统接收到一个其他内容时可以做出反馈。当然,如果玩家想要多次游戏,利用do while()语句就能够轻松解决。

小结:利用switch进行判断玩家的输入1 - play,0 - exit,default - 输入有误。

int input = 0;
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch(input)
        {
            case 1:
            {
                printf("游戏开始!\n");
                Game(); //游戏的实现
                break;
            }
            case 0:
            {
                printf("退出游戏!\n");
                break;
            }
            default:
            {
                printf("输入错误,请重新输入!\n\n");
            }
        }
    }
    while (input);

第二步编写游戏内容

1.游戏的框架

我们进入游戏之后,必然不能是空空荡荡的,下棋必然要有棋盘,有了棋盘再去落子,博弈必然也少不了对手,所以我们从这三个点构建框架。

首先我们要再创建两个文件,第一个是头文件(用于函数的声明),第二个是源文件(用于函数的实现)。在头文件中我们先定义行和列,方便后面的修改。

//头文件名为“五子棋声明”
#include <stdio.h>
#define ROM 3 //行
#define COL 3 //列
#include "五子棋声明.h"//在源文件中对头文件进行声明

1.打印棋盘

2.进行对局

3.分出胜负

由此,我们设一个Game函数

//放于第一个源文件中,主函数也在第一个源文件,源文件可以自行取名
void Game()
{
    //储存数据
     char Board[ROM][COL] = {0};
    //打印棋盘
    DisplayBoard(Board, ROM, COL);
    //对局 (包含玩家下棋与电脑下棋)
    Match(Board, ROM, COL);
}

2.功能的实现

一.打印棋盘

for (int i = 0; i < ROM; i++)
    {
        printf("   |   |   \n");  //里面为三个空格
        if(i < ROM)
        {
            printf("---|---|---\n");
        }
    }

写到此处可能就会有疑问了,这样写不就把代码写死了吗?以后改成五子棋的多行和多列不就很复杂了吗?

是的,这样写确实弊端很大,正如我在大标题下写的,代码是改出来的,在改代码之前一定要把这个构思实现出来,修改时才会有清晰的思路,否则,让一个初学者写上上千行的代码想必很多人刚开始就懵了。通过不断的修改最基本的代码一步一步的扩展,逐渐你就会发现你慢慢的实现了一个自己感觉都不可能完成的事情。就像每天树立一个小目标实现起来并不困难,只要坚持便会收获一份大的成果。

接下来让我们对这个代码进行修改

打印完棋盘后我们发现,没有办法在棋盘上进行下棋,这时就要用到我们的二维数组了,通过二维数组在棋盘上进行坐标的输出。但我们的二维数组里面是空的,所以我们首先要做的是对数组进行初始化,将每个元素都初始化为空格。这时我们将再数组加进去,就达到了我们想要的效果。

//全部在头文件中进行声明
//初始化棋盘 - 初始化空格
void InitBoard(char Board[ROM][COL], int rom, int col);
//打印棋盘
void DisplayBoard(char Board[ROM][COL], int rom, int col);
//函数内容放在第二个源文件中
void InitBoard(char Board[ROM][COL], int rom, int col)
{
    for (int i = 0; i < rom; i++)
    {
        for (int j = 0; j < col; j++)
        {
            Board[i][j] = ' ';
        }
    }
}
//函数内容放在第二个源文件中
void DisplayBoard(char Board[ROM][COL])
{
    for (int i = 0; i < ROM; i++)
    {
        printf(" %c | %c | %c \n", Board[i][0], Board[i][1], Board[i][2]);
        if(i < ROM)
        {
            printf("---|---|---\n");
        }
    }
}

接下来对打印行与列的方式进行修改

通过对输出内容的拆分,寻找其中的规律,利用循环进行输出。这里将‘空格’ 与‘|’进行拆分,‘---’与‘|’进行拆分 ,‘|’每行的输出都少一个,从而建立循环,用if()语句进行判断,使得‘|’的输出比‘ ’和‘---’少一次。同理‘---|---|---’也是如此,用if()语句进行判断,使得他的输出比‘ | | ’少一次。这样我们通过修改ROM和COL的值就可以打印出19路五子棋了。

//函数内容放在第二个源文件中
void DisplayBoard(char Board[ROM][COL])
{
//循环输出,通过更改ROM和COL可以输出自己需要的行数
    for (int i = 0; i < ROM; i++)    
    {
//输出第一行
        for (int j = 0; j < COL; j++)
        {
            printf(" %c ", Board[i][j]);
            if (j < COL - 1)  //最后一个不要
            {
                printf("|");
            }
        }
        printf("\n");
//printf("   |   |   \n");
  
//输出第二行 
        if (i < ROM - 1)  //最后一次输出不要
        {
            for (int j = 0; j < COL; j++)
            {
                printf("---");
                if (j < ROM - 1)  //最后一个不要
                {
                    printf("|");
                }
            }
            printf("\n");
        }
//printf("---|---|---\n");
    }
}

发现问题解决问题

费劲千辛万苦终于把棋盘打印出来了,但打印出来之后你会发现,你在下棋的时候是需要通过输入坐标的输入来下棋的,而棋盘空空荡荡,下起棋来十分不方便,这时你就要再次对自己的代码进行修改。

下面的增加坐标的方式不唯一,我这肯定不是最好的方法,没有办法做到一劳永逸,此处仅供开阔思路吧!

//函数内容放在第二个源文件中
void DisplayBoard(char Board[ROM][COL], int rom, int col)//
{
    //此处为横向坐标的添加
    printf("坐标 1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19\n");
    for (int i = 0; i < rom; i++)
    {
      //此处为纵向坐标的添加
      /*-------------------------------*/
        if (i < 9)
        {
            printf(" %d ", i + 1);
        }
        else if (i >= 9)
        {
            printf(" %d", i + 1);
        }
      /*-------------------------------*/
        for (int j = 0; j < col; j++)
        {
            printf(" %c ",Board[i][j]);
            if (j < col - 1)
            {
                printf("|");
            }
        }
        printf("\n   ");  //此处做了改动
        if (i < rom - 1)
        {
            for (int j = 0; j < col; j++)
            {
                printf("---");
                if (j < col - 1)
                {
                    printf("|");
                }
            }
            printf("\n");
        }
    }
    printf("\n");
}

二.进行对局

1.玩家下棋

//函数内容放在第二个源文件中
void PlayerMove(char Board[ROM][COL])
{
    printf("玩家的坐标:>");
    scanf("%d%d", &x, &y);
    printf("\n");
    Board[x - 1][y - 1] = '*';
}

2.电脑下棋

这里我们先制作一个会落子的电脑玩家

//在头文件中引入函数,用于产生随机数,在此先不细讲了
#include <stdlib.h>
#include <time.h>
srand((int)time(NULL));//放于main函数里的开头位置,用于产生随机数
void ComputerMoves(char Board[ROM][COL])
{
    x = rand()%ROM;//产生纵向随机数0 ~ (ROM - 1)
    y = rand()%COL;//产生横向随机数0 ~ (COL - 1)
    Board[x][y] = '#';
    printf("电脑的坐标:>%d %d\n\n", x, y);
}

发现问题

运行后你会发现什么都没有打印,这时你就要再次数将原先的打印棋盘的函数家在此处。

你再次运行程序后会发现,你的棋子可以覆盖掉电脑的棋子,反之电脑也可以覆盖你的棋子,这时我们就要针对这个问题再进行完善。

解决问题

在这里我们需要再加一个判断条件和一个循环语句,当判断此处已经落子后,可以让我们从新输入。而电脑玩家此处只需要加上一个判断就可以了。完善后的代码如下

//玩家下棋
void PlayerMove(char Board[ROM][COL])
{
    int x, y;
    printf("玩家的回合!\n");
    while (1)
    {
        printf("玩家的坐标:>");
        scanf("%d%d", &x, &y);
        printf("\n");
        if (Board[y - 1][x - 1] == ' ') // 判断此处是否已经落子
        {
            Board[y - 1][x - 1] = '*';
            break;
        }
        else
        {
            printf("该坐标已落子!\n");
            printf("请重新输入!\n");
        }
    }
    DisplayBoard(Board, ROM, COL); // 输入成功后,打印棋盘
}

//电脑玩家下棋
void ComputerMove(char Board[ROM][COL])
{
    int x, y;
    while (1)
    {
        x = rand()%ROM;
        y = rand()%COL;
        if (Board[x][y] == ' ')
        {
            Board[x][y] = '#';
            printf("电脑的回合!\n");
            printf("电脑的坐标:>%d %d\n\n", y, x); // 这里输出时不要搞反
            break;
        }
    }
    DisplayBoard(Board, ROM, COL);
}

3.对局

我们将前面的内容整合一下就可以得到下面的代码

void Match(char Board[ROM][COL], int rom, int col)
{
    while (1)
    {
        //玩家下棋
        PlayerMove(Board);
        count++;
        if (count == rom*col) // 判断棋盘是否已经占满,棋盘格子的数目为(ROM * COL)为单数所以放在中间
        {
            printf("平局!");
            break;
        }
        //电脑下棋
        ComputerMove(Board);
        count++;
    }
}

三.分出胜负

五子棋判断输赢无非就是某一方的棋在一条直线上连出5个棋子,由此我们可以分成以下四种情况

? ? ? ? 1.纵向连成5个棋子

? ? ? ? 2.横向连成5个棋子

? ? ? ? 3.斜率 == 1时,连成五个棋子

? ? ? ? 4.斜率 == -1时,连成五个棋子

1.纵向判断

在这里我使用的是纵向遍历的方法,最开始纵向的五个值,沿着纵向进行遍历。

void Win1(char Board[ROM][COL], int rom, int col, char *Ret)
{
    int x = 0;
    int y = 0;
    for (y = 0; y <= col; y++ && *Ret != 'W')
    {
        for (x = 0; x <= rom - 5; x++) 
        //(rom - 5)是指后面的四个数不需要在遍历,Board[x + 4]已经将其覆盖了
        {
            if (Board[x][y] == Board[x + 1][y] && Board[x + 1][y] == Board[x + 2][y] && Board[x + 2][y] == Board[x + 3][y] && Board[x + 3][y] == Board[x + 4][y] && Board[x][y] != ' ') // 这里的方法很笨,直接判断5个值知否相等
            {
                *Ret = 'W'; //这里的指针用于直接改变结果,不需要再返回值
                break;
            }
        }
    }
}

2.横向判断

与纵向判断一样,最开始横向的五个值,沿着横向进行遍历。

void Win2(char Board[ROM][COL], int rom, int col, char *Ret)
{
    int x = 0;
    int y = 0;
    for (x = 0; x <= rom; x++ && *Ret != 'W')
    {
        for (y = 0; y <= col - 5; y++)
        {
            if (Board[x][y] == Board[x][y + 1] && Board[x][y + 1] == Board[x][y + 2] && Board[x][y + 2] == Board[x][y + 3] && Board[x][y + 3] == Board[x][y + 4] && Board[x][y] != ‘ ’)
            {
                *Ret = 'W';
                break;
            }
        }
    }
}

3.斜率 == 1方向

判断方法与前面一样,只不过变成了倾斜的方向,起始点为左上角(1,1)

从红线开始遍历,沿着斜率 == -1的白线到方向,一条路向左下遍历到5个红点的位置,另一条路向右上遍历到仅容纳5个点的右上角。每向 (白线)- 1方向(上/下)挪动时,都会少遍历一格,直至仅有五格的时候停止遍历,因此在循环的时候ROM和COL均减去5。

void Win3(char Board[ROM][COL], int rom, int col, char *Ret)
{
    int x = 0;
    int y = 0;
    int xs = 0;
    int ys = 0;
    for (xs = 0; xs <= rom - 5 && *Ret != 'W'; xs++)//沿-1方向向下遍历
    {
        x = xs;
        for (y = 0; y <= col - 5 && x <= rom - 5; y++, x++)//
        {
            if (Board[x][y] == Board[x + 1][y + 1] && Board[x + 1][y + 1] == Board[x + 2][y + 2] && Board[x + 2][y + 2] == Board[x + 3][y + 3] && Board[x + 3][y + 3] == Board[x + 4][y + 4] && Board[x][y] != ' ')
            {
                *Ret = 'W';
                break;
            }
        }
    }
    for (ys = 0; ys <= col - 5 && *Ret != 'W'; ys++)//沿-1方向向上遍历
    {
        y = ys;
        for (x = 0; y <= col - 5 && x <= rom - 5; y++, x++)
        {
            if (Board[x][y] == Board[x + 1][y + 1] && Board[x + 1][y + 1] == Board[x + 2][y + 2] && Board[x + 2][y + 2] == Board[x + 3][y + 3] && Board[x + 3][y + 3] == Board[x + 4][y + 4] && Board[x][y] != ' ')
            {
                *Ret = 'W';
                break;
            }
        }
    }
}

4.斜率 == -1方向

方法与斜率 == 1相同,不同点在于改变了起始点为(COL - 1)

这次是从白线开始遍历,沿着斜率 == 1红线的方向分为两条路,第一条为左上,第二条为右下,遍历到仅容纳5个点的位置停止遍历。

//赢法四(判断斜率 == -1时)
void Win4(char Board[ROM][COL], int rom, int col, char *Ret)
{
    int x = 0;
    int y = 0;
    int xs = 0;
    int ys = col - 1;
    for (xs = 0; xs <= rom - 5 && *Ret != 'W'; xs++)
    {
        x = xs;
        for (y = col - 1; y >= 4 && x <= rom - 5; y--, x++)
        {
            if (Board[x][y] == Board[x + 1][y - 1] && Board[x + 1][y - 1] == Board[x + 2][y - 2] && Board[x + 2][y - 2] == Board[x + 3][y - 3] && Board[x + 3][y - 3] == Board[x + 4][y - 4] && (Board[x][y] == '#' || Board[x][y] == '*'))
            {
                *Ret = 'W';
                break;
            }
        }
    }
    for (ys = col - 1;ys >= 4 && *Ret != 'W'; ys--)
    {
        y = ys;
        for (x = 0; y >= 4 && x <= rom - 5; y--, x++)
        {
            if (Board[x][y] == Board[x + 1][y - 1] && Board[x + 1][y - 1] == Board[x + 2][y - 2] && Board[x + 2][y - 2] == Board[x + 3][y - 3] && Board[x + 3][y - 3] == Board[x + 4][y - 4] && (Board[x][y] == '#' || Board[x][y] == '*'))
            {
                *Ret = 'W';
                break;
            }
        }
    }
}

根据以上四种判断方法,我们就可以判断谁胜谁负了,但在此之前还是要把他们整理到一起

//判断赢得对局
char WinMatch(char Board[ROM][COL])
{
    char Ret = 'F'; //Ret = 'W';判断出了结果的同时,也不会再跑完其他的函数
    Win1(Board, ROM, COL, &Ret);
    Win2(Board, ROM, COL, &Ret);
    Win3(Board, ROM, COL, &Ret);
    Win4(Board, ROM, COL, &Ret);
    return Ret;
}

优化和完善一下我们的对局

//对局
void Match(char Board[ROM][COL], int rom, int col)
{
    int OrWin = 'F'; // 接收返回的Ret结果
    int count = 0;
    while (1)
    {
        //玩家下棋
        printf("第 %d 回合!\n",count + 1);
        PlayerMove(Board);
        OrWin = WinMatch(Board);//判断对局是否赢了
        count++;                //记录回合数
        if (OrWin == 'W')
        {
            printf("恭喜你赢了!\n");
            printf("玩家胜利!\n\n");
            break;
        }

        //判断回合是否已满
        else if (count == rom * col)
        {
            printf("平局!\n\n");
            break;
        }

        //电脑下棋
        printf("第 %d 回合!\n",count + 1);
        ComputerMoves(Board);
        OrWin = WinMatch(Board);//判断对局是否赢了
        count++;                //记录回合数
        if (OrWin == 'W')
        {
            printf("很遗憾你输了!\n");
            printf("电脑胜利!\n");
            break;
        }
    }
}

头文件整理

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROM 19
#define COL 19

//菜单
void menu();
//五子棋主函数
void Game();

//主函数(内部)
//初始化棋盘 - 初始化空格
void InitBoard(char Board[ROM][COL], int rom, int col);
//打印棋盘
void DisplayBoard(char Board[ROM][COL], int rom, int col);
//玩家下棋
void PlayerMove(char Board[ROM][COL]);
//电脑(简单)算法下棋
void ComputerMoves(char Board[ROM][COL]);
//对局
void Match(char Board[ROM][COL], int rom, int col);
//判断赢得对局
char WinMatch(char Board[ROM][COL]);

//判断赢得对局(内部)
//赢法一(判断列)
void Win1(char Board[ROM][COL], int rom, int col, char *Ret);
//赢法二(判断行)
void Win2(char Board[ROM][COL], int rom, int col, char *Ret);
//赢法三(判断斜率 == 1时)
void Win3(char Board[ROM][COL], int rom, int col, char *Ret);
//赢法四(判断斜率 == -1时)
void Win4(char Board[ROM][COL], int rom, int col, char *Ret);

Game函数

void Game()
{
    //储存数据 - 二维数组
    char Board[ROM][COL] = {0};
    //初始化棋盘 - 初始化空格
    InitBoard(Board, ROM, COL);
    //打印棋盘
    DisplayBoard(Board, ROM, COL);
    //对局
    Match(Board, ROM, COL);
}

除Game函数以外,我将其他的函数都放到了源文件(2),并将其命名为Game

这样我们就成功完成了我们的五子棋小游戏!

第三步编写电脑玩家

由于我水平确实很有限,就电脑玩家写了就有1000行,真就是技术不够代码来凑啊...所以在这里我只给大家分享一下思路也欢迎各位的指点交流!

1.分类

//电脑算法头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROM 19
#define COL 19

//电脑(简单)算法下棋(内部)
void ComputerMain (char Board[ROM][COL], int *x, int *y, int *stop);

//算法(初始点设定)
void  ComputerC1(char Board[ROM][COL], int *px, int *py, int *stop);
//算法(随机点产生)
void  ComputerC2(char Board[ROM][COL], int *px, int *py, int *stop);

//连珠算法常规
//算法一(纵向)
void  ComputerM1(char Board[ROM][COL],int *px, int *py, int *stop, int N);
//算法二(横向)
void  ComputerM2(char Board[ROM][COL], int *px, int *py, int *stop, int N);
//算法三(斜率 == 1方向)
void  ComputerM3(char Board[ROM][COL], int *px, int *py, int *stop, int N);
//算法四(斜率 == -1方向)
void  ComputerM4(char Board[ROM][COL], int *px, int *py, int *stop, int N);
//算法一选择
void ComputerM1_1(char Board[ROM][COL],int x, int y, int *px, int *py, int *stop, int N);
//算法二选择
void ComputerM2_1(char Board[ROM][COL],int x, int y, int *px, int *py, int *stop, int N);
//算法三选择
void ComputerM3_1(char Board[ROM][COL],int x, int y, int *px, int *py, int *stop, int N);
//算法四选择
void ComputerM4_1(char Board[ROM][COL],int x, int y, int *px, int *py, int *stop, int N);

//一字缺口算法
//缺口算法一(纵向)
void  ComputerG1(char Board[ROM][COL], int *px, int *py, int *stop);
//缺口算法二(横向)
void  ComputerG2(char Board[ROM][COL], int *px, int *py, int *stop);
//缺口算法三(斜率 == 1方向)
void  ComputerG3(char Board[ROM][COL], int *px, int *py, int *stop);
//缺口算法四(斜率 == -1方向)
void  ComputerG4(char Board[ROM][COL], int *px, int *py, int *stop);
//缺口算法五(纵向)
void  ComputerG5(char Board[ROM][COL], int *px, int *py, int *stop);
//缺口算法六(横向)
void  ComputerG6(char Board[ROM][COL], int *px, int *py, int *stop);
//缺口算法七(斜率 == 1方向)
void  ComputerG7(char Board[ROM][COL], int *px, int *py, int *stop);
//缺口算法八(斜率 == -1方向)
void  ComputerG8(char Board[ROM][COL], int *px, int *py, int *stop);

//回字缺口算法
//缺口算法九(空心三乘三)
void  ComputerG9(char Board[ROM][COL], int rom, int col, int *px, int *py, int *stop);
//缺口算法十(空心七乘七)
void  ComputerG10(char Board[ROM][COL], int rom, int col, int *px, int *py, int *stop);
//缺口算法十一(空心九乘九)
void  ComputerG11(char Board[ROM][COL], int rom, int col, int *px, int *py, int *stop);
//缺口算法(回字三乘三)四向
void ComputerG9_1(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(回字七乘七)纵向
void  ComputerG10_1(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(回字七乘七)横向
void  ComputerG10_2(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(回字七乘七)斜率 == 1方向
void  ComputerG10_3(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(回字七乘七)斜率 == -1方向
void  ComputerG10_4(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(回字九乘九)纵向
void  ComputerG11_1(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(回字九乘九)横向
void  ComputerG11_2(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(回字九乘九)斜率 == 1方向
void  ComputerG11_3(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(回字九乘九)斜率 == -1方向
void  ComputerG11_4(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);
//缺口算法(选择输出)
void Cret(char Board[ROM][COL], int x, int y, int *ret1, int *ret2);

2.输出顺序

下面的注释是对一个标题的整体解释,四个为一组的标题依然是按照 纵向、横向、k == 1、k == -1 来编写的。我方永远在敌方前面判断,如果我方不符合,在判断敌方是否构成威胁。

void ComputerMain (char Board[ROM][COL],int *x, int *y, int *stop)
{
    //五子缺一子
    ComputerG8(Board, x, y, stop); //五子缺一子,说白了就是连成了4个棋子
    ComputerG7(Board, x, y, stop); //我方:下到这一步直接胜利
    ComputerG6(Board, x, y, stop); //敌方:必须封住着一颗棋子否则输
    ComputerG5(Board, x, y, stop); //缺少的是中间三颗棋子的其中一颗
    //四子连珠(一空/两空)
    ComputerM4(Board, x, y, stop,2); //四颗棋子连在一起,两边有空,或者一边有空
    ComputerM3(Board, x, y, stop,2); //我方:下到这一步直接胜利
    ComputerM2(Board, x, y, stop,2); //敌方:必须封住着一颗棋子否则输,也有可能是必输
    ComputerM1(Board, x, y, stop,2); 
    //四子缺一子
    ComputerG4(Board, x, y, stop); //判断四颗棋子中间两个子棋缺少任意一个
    ComputerG3(Board, x, y, stop); 
    ComputerG2(Board, x, y, stop);
    ComputerG1(Board, x, y, stop);
    //回字缺口(九乘九)
    ComputerG11(Board, ROM, COL, x, y, stop); //用于判断九成九的格子内的交叉棋,并封堵
                                              //建议11*11更全面,我这里有一种情况会误判,正在改ing
    //三子连珠(一空/两空)(敌方两空)
    ComputerM4(Board, x, y, stop,1); //三个棋子连在一起,两边都有空,或一边有空
    ComputerM3(Board, x, y, stop,1); //我方:直接下,一空拖一手,两空有机会赢
    ComputerM2(Board, x, y, stop,1); //敌方:一空就不用管了,两空肯定要封
    ComputerM1(Board, x, y, stop,1);
    //回字缺口(七乘七)
    ComputerG10(Board, ROM, COL, x, y, stop); //这里要注意,这是两子和三子的交叉棋
                                              //一个方向两子加三子的情况之和就有5种
                                              //交叉方式更多,所以要格外注意,目前我这里没发现漏洞
    //回字缺口(三乘三)
    ComputerG9(Board, ROM, COL, x, y, stop); //这里就是十字棋的情况了,优先级比较低,但是也够用
    //电脑二子连珠(两空)
    ComputerM4(Board, x, y, stop,0); //这里就是我方的下棋方法了,我偏向于斜着下
    ComputerM3(Board, x, y, stop,0); //这里面是很值得研究的,但是我下棋本就没啥章法
    ComputerM2(Board, x, y, stop,0); //所以这块我也没有什么路数,等Bug修完,打算再研究
    ComputerM1(Board, x, y, stop,0); //如果是敌方:我直接就没管他
    //电脑的初始点
    ComputerC1(Board, x, y, stop); //初始点我设置了几个我自认为毕竟好的开局点位,我防止电脑开局乱下
    //电脑的随机点
    ComputerC2(Board, x, y, stop); //我设置了两个随机点
                                   //第一个,我以中心为范围的7*7随机点,注意不要死循环
                                   //第二个,我设的全局随机点,防止7*7范围下满
}

我的思路可能不全,打算等在学一段时间之后,又能好的方法可以将我原先的代码更替掉,然后研究一下大佬们的思路。也慢慢的去学习如何做到高内聚低耦合,现在感觉还是多少又一些困难再接再厉吧!

总结

感觉自己还是有点作,无论啥编程题,我都想尽办法看看能不能把题目变得复杂一点感觉有挑战性,以至于总是比其他人的代码多上连三倍。殊不知这次改三子棋的题结果给玩大了,以至于我再历经三天的不眠之战,一直在修BUG和修BUG的路上,情人节愣是跟BUG约会了一天......不过历经这次的鏖战,我慢慢的相信代码是改出来的,从一个很小很小的三子棋,慢慢的改成五子棋,思路一点一点点拓宽,问题也一点点暴露出来,同时我也在一点一滴的往前走着,虽然过程很艰辛,但真的很快乐,第一次写这么多代码,还是独立完成,真的很有成就感的。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-19 00:58:09  更:2022-02-19 00:59:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:46:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码