我可能写的有些啰嗦,见谅,但我会很详细的讲解每一个步骤。

分析步骤

  • 游戏框架的构造(游戏结构的设计)
    • 代码布局设计
      • 对游戏布局,初始选项的思考
  • 将上述游戏设计实现
    • 判断棋盘的局面
      • char ifdraw(char board[ROW][COL])
    • 计算机堵截玩家的算法设计:思路
  • 主函数界面
    • game.c
      • game.h

游戏框架的构造(游戏结构的设计)

1,游戏需要菜单
2,需要选项(进入游戏或退出)
3,三子棋需要一个3*3的棋盘
4,需要将棋盘表现(打印出来)
5,玩家要开始下棋(输入坐标)
6,每次落子后都要判断输赢或平局
7,打印目前棋盘的状况
8,电脑开始落子
9,每次落子后都要判断输赢或平局
10,打印目前棋盘的状况
11.判断游戏目前的局面(输或赢,继续落子或者平局)

代码布局设计

由于,代码量过大,并且各个函数的设计及作用。并且考虑N子棋的可能。我们需要分模块,分文件来写。

对游戏布局,初始选项的思考

游戏菜单-进入游戏或者退出—分支语句(switch)
还要打印游戏菜单,使用函数。
为了多次play游戏,也包括多次选项输入,考虑do{}while();循环,可以至少进入一次循环。

void option(int input)
{switch (input)//分支语句{case 1:game();//进入游戏break;case 0:printf("Logon out the game\n");break;default:printf("Input error,please input again\n");break;}
}
void menu(void)
{printf("Welcome to game\n");printf("\n");printf("****************\n");printf("*----1.play----*\n");printf("*----0.exit----*\n");printf("****************\n");
}
int main(void)
{int input;//srand((unsigned int)time(NULL));时间戳,为电脑落子设定随机数do{menu();//打印游戏菜单printf("please input option(1/0):>");scanf("%d", &input);option(input);//选项判断} while (input);return 0;
}

我们要求输入数字1或0,如果输入其他值,就会default结束,并进入while判断,为,int型,再次循环。

game函数的实现

  • 游戏框架的构造(游戏结构的设计)
    • 代码布局设计
      • 对游戏布局,初始选项的思考
  • 将上述游戏设计实现
    • 判断棋盘的局面
      • char ifdraw(char board[ROW][COL])
    • 计算机堵截玩家的算法设计:思路
  • 主函数界面
    • game.c
      • game.h

将上述游戏设计实现

1,三子棋需要一个3*3的棋盘
2,需要将棋盘表现(打印出来)
3.玩家要开始下棋(输入坐标)
4.每次落子后都要判断输赢或平局
5,打印目前棋盘的状况
6,电脑开始落子
7,每次落子后都要判断输赢或平局
8,打印目前棋盘的状况

void game(void)
{char ret;char board[ROW][COL];//创建二维数组setboard(board, ROW, COL);//制作棋盘while (1){player(board);//玩家开始下棋ret=judgewinner(board);//判断输赢if (ret != 'C')break;computer(board);//电脑开始下棋ret=judgewinner(board);//判断输赢if (ret != 'C')break;}if (ret == '*')printf("The winner is player\n");else if (ret == '#')printf("The winner is computer\n");else if (ret == 'D')printf("Player and computer draw\n");}

1,三子棋需要一个3*3的棋盘
毕竟是个3 * 3的棋盘,可以使用二维数组。
char board[3][3]//这两个行列可以使用宏定义常量,方便延申N子棋。
#define ROW 3
#define COL 3
char board[ROW][COL]

2, 打印三子棋棋盘

大概是这样的

二维数组的元素也要被定义为空格。在后面玩家或电脑输入后可以被重新定义为*号或#号。

void setboard(char board[ROW][COL], int row, int col)//制作第一个棋盘
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){board[i][j] = ' ';//元素被定义为空格}}showboard(board,ROW, COL);//打印棋盘的函数
}
void showboard(char board[ROW][COL], int row, int col)//打印棋盘
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col)printf("|");}if (i < row)printf("\n---|---|---|\n");}
}

3,玩家落子

就是输入坐标

void player(char board[ROW][COL])//玩家下棋
{int x, y;while (1){printf("please input the coordinate:>");scanf("%d %d", &x, &y);//输入要落子的坐标if (x>=1&&x<=ROW&&y>=1&&y<=COL)//判断该坐标处,是否未被输入过{if (board[x - 1][y - 1] != ' ')printf("Coordinates occupied,please input again\n");else{board[x - 1][y - 1] = '*';break;}}elseprintf("Coordinate is illegal,please input again\n");//被使用过,重新输入}//printf("*******************\n");printf("Player\n");showboard(board, ROW, COL);//打印每次下棋后的棋盘
}

由于玩家并不是程序员不认为,起点是0,所以赋值时要x-1,y-1.。
并且这是多次输入,要保证输入那个坐标处不能已经输入过,就是说要保证该数组元素只能为空格。同时还要保证输入坐标要有效,必须在33的棋盘内,如果两个问题有一个存在,必须要重新输入,所以放入循环内,直到输入正确,才会跳出循环。

4,先不考虑判断输赢,先打印当前棋盘,就是调用showboard(board, ROW, COL);函数,循环打印。

先保证电脑和玩家的棋盘输入输出正确再来判断输赢。

6,电脑开始落子,打印棋盘

暂时先使用随机落子的算法,下次我再写堵截玩家落子的算法

void computer(char board[ROW][COL])//电脑落子
{while (1){int x = rand() % ROW;int y = rand() % COL;if (board[x][y] == ' ')//判断该坐标处,是否未被输入过{board[x][y] = '#';break;}}printf("Computer\n");//printf("*******************\n");showboard(board, ROW, COL);//打印每次下棋后的棋盘
}

前面已经使用srand();,保证了随机数

int x = rand() % ROW;
int y = rand() % COL;

X y,为随机数除以排或列的余数,也就是说xy的值必定小于排,列的值,也就保证了xy,为 0,1,2
这也同样保证了由三子棋走向N子棋的条件。
同样得保证电脑落子的坐标处不能已经使用过,必须得保证坐标元素处为空格,才能输入#。并且调用函数打印当前棋盘。

判断棋盘的局面

调用char judgewinner(char board[ROW][COL])函数

char ifdraw(char board[ROW][COL])
{int i;for (i = 0; i < ROW; i++){int j;for (j = 0; j < COL; j++){if (board[i][j] == ' ')return 'C';}}return 'D';
}
char judgewinner(char board[ROW][COL])
{int count;//判断一行赢for (int i = 0; i < ROW; i++){int j,count=0;for (j = 0; j < COL-1; j++){if (board[i][j] != board[i][j + 1])break;else if (board[i][j] == board[i][j + 1])count++;}if (count == COL - 1){if (board[i][j] == '*')return '*';//玩家赢else if (board[i][j] == '#')return '#';//电脑赢}if ((count != COL - 1) && (i == ROW - 1))return ifdraw(board);//平局}//判断列赢for (int i = 0; i < COL; i++){int j, count = 0;for (j = 0; j < ROW - 1; j++){if (board[i][j] != board[i][j + 1])break;else if (board[i][j] == board[i][j + 1])count++;}if (count == ROW - 1){if (board[i][j] == '*')return '*';//玩家赢else if (board[i][j] == '#')return '#';//电脑赢}if ((count != ROW - 1) && i == COL - 1)return ifdraw(board);//平局}//判断对角线\赢count = 0;int i = 0;int j;while ((count != COL - 1) && (i <ROW-1)){j = i;if (board[i][j] == board[i + 1][j + 1])count++;else if (board[i][j] != board[i + 1][j + 1])break;i++;if (count == ROW - 1){if (board[i][j] == '*')return '*';//玩家赢else if (board[i][j] == '#')return '#';//电脑赢}}return ifdraw(board);//平局}//对角线/count=0;i = ROW - 1;while (i>0){j=ROW-i-1;if (board[i][j] == board[i - 1][j + 1])count++;else if (board[i][j] = board[i - 1][j + 1])break;i--;if (count == COL - 1){if (board[i][j] == '*')return '*';//玩家赢else if (board[i][j] == '#')return '#';//电脑赢}}return ifdraw(board);//平局}

判断一行或者一列的棋子都相等的情况下,我们使用l两个for循环,我们同时定义一个控制变量。外循环,保证每一个行或每列都能覆盖。内循环来确定每一行或每一列上的元素,相邻之间是否相等?如果相等,count加一,不相等就可以确定,不存在决定当前棋局的条件,直接跳出。同样支持N子棋的判断。

对于左斜线以及右斜线上的三指相的条件,这个就比较简单,,不需要一遍遍的遍历,只需要找到特定的三个元素去判断是否相等即可得出条件。

用这些循环条件来判断,只能得出是否是玩家赢还是电脑赢,但是还需要添加一个函数来判断是否是平局或者棋局未满,可以继续落子。

char ifdraw(char board[ROW][COL])

判断平局或继续落子。

用两个for循环去遍历数组只要判断出有一个元素是空格隔那么就返回c就可以直接得出可以继续落子,就需要返回来D来决定已经平局无法再落子。
因为一旦进入这卡数就表明已经判断出无法决定谁胜或者谁负,只能继续走两条路一就是平局,二就是继续落子

同时,设定了ret来接受judgewinner(char board[ROW][COL])函数的返回值,来判断是否可以继续循环落子。

计算机堵截玩家的算法设计:思路

游戏的规则是行列斜线,三种情况下,只要有一种情况,该线上都归属于三个同样的旗子,即可判断输赢
我们可以考虑循环遍历
依靠循环进入每行每列,每个斜线,进行每个元素的遍历,如果该行该列或该斜线上有两个相同的元素,立马在第三个元素上进行,若无论是否与自己相同.

该思路目前只适用于三字棋,也可延伸到四子棋,4则是两个起步,如果该列该行或该切线上有两个以上的相同元素,就立马在第三或第四个元素中进行落子

以下便是为拆开讲解的全部代码。

三子棋

  • 游戏框架的构造(游戏结构的设计)
    • 代码布局设计
      • 对游戏布局,初始选项的思考
  • 将上述游戏设计实现
    • 判断棋盘的局面
      • char ifdraw(char board[ROW][COL])
    • 计算机堵截玩家的算法设计:思路
  • 主函数界面
    • game.c
      • game.h

主函数界面

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "game.h"
#define ROW 3
#define COL 3
//返回值
//*
//#
//C-继续
//D-平局
void game(void)
{char ret;char board[ROW][COL];//创建二维数组setboard(board, ROW, COL);//制作棋盘while (1){player(board);//玩家开始下棋ret=judgewinner(board);//判断输赢if (ret != 'C')break;computer(board);//电脑开始下棋ret=judgewinner(board);//判断输赢if (ret != 'C')break;}if (ret == '*')printf("The winner is player\n");else if (ret == '#')printf("The winner is computer\n");else if (ret == 'D')printf("Player and computer draw\n");}
void option(int input)
{switch (input)//分支语句{case 1:game();break;case 0:printf("Logon out the game\n");break;default:printf("Input error,please input again\n");break;}
}
void menu(void)
{printf("Welcome to game\n");printf("\n");printf("****************\n");printf("*----1.play----*\n");printf("*----0.exit----*\n");printf("****************\n");
}
int main(void)
{int input;srand((unsigned int)time(NULL));do{menu();//打印游戏菜单printf("please input option(1/0):>");scanf("%d", &input);option(input);//选项判断} while (input);
}

game.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "game.h"
//void game(void)
//{//  char board[ROW][COL];//创建二维数组
//  setboard(board, ROW, COL);//制作棋盘
//  player(board);//玩家开始下棋
//
//  computer(board);//电脑开始下棋
//
//}
void setboard(char board[ROW][COL], int row, int col)//制作第一个棋盘
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){board[i][j] = ' ';}}showboard(board,ROW, COL);
}
void showboard(char board[ROW][COL], int row, int col)//打印棋盘
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col)printf("|");}if (i < row)printf("\n---|---|---|\n");}
}
void player(char board[ROW][COL])//玩家下棋
{int x, y;while (1){printf("please input the coordinate:>");scanf("%d %d", &x, &y);//输入要落子的坐标if (x>=1&&x<=ROW&&y>=1&&y<=COL)//判断该坐标处,是否未被输入过{if (board[x - 1][y - 1] != ' ')printf("Coordinates occupied,please input again\n");else{board[x - 1][y - 1] = '*';break;}}elseprintf("Coordinate is illegal,please input again\n");//被使用过,重新输入}//printf("*******************\n");printf("Player\n");showboard(board, ROW, COL);//打印每次下棋后的棋盘
}
void computer(char board[ROW][COL])//电脑落子
{while (1){int x = rand() % ROW;int y = rand() % COL;if (board[x][y] == ' ')//判断该坐标处,是否未被输入过{board[x][y] = '#';break;}}printf("Computer\n");//printf("*******************\n");showboard(board, ROW, COL);//打印每次下棋后的棋盘
}
char ifdraw(char board[ROW][COL])
{int i;for (i = 0; i < ROW; i++){int j;for (j = 0; j < COL; j++){if (board[i][j] == ' ')return 'C';}}return 'D';
}
char judgewinner(char board[ROW][COL])
{int count;//判断一行赢for (int i = 0; i < ROW; i++){int j,count=0;for (j = 0; j < COL-1; j++){if (board[i][j] != board[i][j + 1])break;else if (board[i][j] == board[i][j + 1])count++;}if (count == COL - 1){if (board[i][j] == '*')return '*';//玩家赢else if (board[i][j] == '#')return '#';//电脑赢}if ((count != COL - 1) && (i == ROW - 1))return ifdraw(board);//平局}//判断列赢for (int i = 0; i < COL; i++){int j, count = 0;for (j = 0; j < ROW - 1; j++){if (board[i][j] != board[i][j + 1])break;else if (board[i][j] == board[i][j + 1])count++;}if (count == ROW - 1){if (board[i][j] == '*')return '*';//玩家赢else if (board[i][j] == '#')return '#';//电脑赢}if ((count != ROW - 1) && i == COL - 1)return ifdraw(board);//平局}//判断对角线\赢count = 0;int i = 0;int j;while ((count != COL - 1) && (i <ROW-1)){j = i;if (board[i][j] == board[i + 1][j + 1])count++;else if (board[i][j] != board[i + 1][j + 1])break;i++;if (count == ROW - 1){if (board[i][j] == '*')return '*';//玩家赢else if (board[i][j] == '#')return '#';//电脑赢}}return ifdraw(board);//平局}//对角线/count=0;i = ROW - 1;while (i>0){j=ROW-i-1;if (board[i][j] == board[i - 1][j + 1])count++;else if (board[i][j] = board[i - 1][j + 1])break;i--;if (count == COL - 1){if (board[i][j] == '*')return '*';//玩家赢else if (board[i][j] == '#')return '#';//电脑赢}}return ifdraw(board);//平局}

game.h

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void game(void);//三子棋游戏
void setboard(char board[ROW][COL], int row, int col);//创建棋盘
void showboard(char board[ROW][COL], int row, int col);//打印、展示棋盘
void player(char board[ROW][COL]);//玩家落子
void computer(char board[ROW][COL]);//电脑落子
char judgewinner(char board[ROW][COL]);//判断输赢
char ifdraw(char board[ROW][COL]);//判断是否平局

三子棋-支持N子棋-详解(以及堵截玩家的方法设计)相关推荐

  1. 三子棋(N子棋)小游戏超详解

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.三子棋的游戏规则? 二.三子棋的游戏设计的大概思路? 三.设计详细思路加代码 1.首先定义一个菜单menu函数 2 ...

  2. c语言入门——三子棋(N子棋)

    目录 前言 一.什么是三子棋? 二.三子棋(N子棋)设计思路 1.主函数 2.数组的初始化 3.菜单 4.游戏主体 (1).棋盘 (2).下棋 (3).判断胜负 三.最终代码 源文件1 源文件2 头文 ...

  3. c语言实现三子棋(井子棋)

    目录 前言 一.初步构思 二.实现步骤 1.text.c 2.game.c 3.game.h 总结 前言 通过对c语言的初步学习,我们可以用循环,数组,函数的相关知识写一个简单的游戏.增强自信心的同时 ...

  4. oracle做子查询注意事项,Oracle子查询详解

    Oracle子查询详解,根据查询的结果(内部嵌套查询的结果)把子查询的类型分为单行子查询与多行子查询, 子查询概念 :当一个查询的结果是另一个查询的条件时,,称之为子查询. 使用子查询注意事项: 子查 ...

  5. 推子五子棋、连六棋(六子棋)

    目录 推子五子棋 连六棋 推子五子棋 在线play 规则: 在5*5的盘面上下五子棋,正常肯定会下满25个格子,然后开始推子操作: 在一个格子落子,这个格子以及这一列它下面的(1-5个)所有格子都往下 ...

  6. oracle之子查询_,Oracle子查询详解

    Oracle子查询详解,根据查询的结果(内部嵌套查询的结果)把子查询的类型分为单行子查询与多行子查询, 子查询概念 :当一个查询的结果是另一个查询的条件时,,称之为子查询. 使用子查询注意事项: 子查 ...

  7. K8s系列之:kubectl子命令详解edit

    K8s系列之:kubectl子命令详解edit 在服务器上使用默认编辑器资源,使用这个命令可以编辑多个对象,然后一次性地应用更改. #编辑名为nginx的服务 kubectl edit svc ngi ...

  8. K8s系列之:kubectl子命令详解explain

    K8s系列之:kubectl子命令详解explain 资源记录.获取资源及其字段的文档. kubectl explain pods#获取资源的特定字段的文档 kubectl explain pods. ...

  9. jQuery选择器代码详解(一)——Sizzle方法

    对jQuery的Sizzle各方法做了深入分析(同时也参考了一些网上资料)后,将结果分享给大家.我将采用连载的方式,对Sizzle使用的一些方法详细解释一下,每篇文章介绍一个方法. 若需要转载,请写明 ...

最新文章

  1. 资源 | AI、神经网络、机器学习、深度学习以及大数据学习备忘单
  2. Scrum敏捷看板工具leangoo-销售流程管理
  3. php中添加访问器,php – 结合访问器和mutator逻辑,为模型添加自定义属性
  4. POJ3614奶牛晒阳光DINIC或者贪心
  5. Windows环境下搭建React Native
  6. php向ldap插入数据,给LDAP添加用户,构造用户文件,然后使用phpLadpadmin导入
  7. 《从0到1学习Flink》—— 介绍Flink中的Stream Windows
  8. 白帽子学Linux教程,网络安全工程师与白帽子***教你Kali Linux***:内网***实战技巧...
  9. Laravel 数据库实例教程 —— 使用DB门面操作数据库
  10. MySQL远程连接ERROR 2003 (HY000) Cant connect to MySQL server on (10060)
  11. 【Flutter】微信项目实战【02】我的界面搭建(上)
  12. EDM营销常见问题之邮件被退回原因剖析
  13. 平安科技测试面试经验分享
  14. w7计算机删除图标不见了怎么办,win7小电脑图标不见了怎么办
  15. Android Studio:使用SVN进行版本控制
  16. java.lang.RuntimeException: Parcel: unable to marshal value com.
  17. win10系统 oracle11g的安装流程
  18. YOLOV5:在本地电脑训练模型
  19. 品优购电商系统开发----商品录入《一》(5)
  20. oracle ogg下载安装,【OGG】OGG的下载和安装篇

热门文章

  1. 为什么我的传奇版本右键穿不了装备怎么办?
  2. Spider实战系列-爬取小说
  3. 印象笔记改变背景颜色
  4. 2021年安徽省高考成绩查询窗口,安徽省教育招生考试院:2021年安徽高考查分入口、查分系统...
  5. 王者荣耀五周年,带你入门Python爬虫基础操作!
  6. 基于时序特征处理与LSTM结合的雅虎美股数据预测
  7. vivo Xplay 5的Usb调试模式在哪里,打开vivo Xplay 5Usb调试模式的经验
  8. 世界末日生存服务器中断,生存新作《最后的绿洲》服务器检修 Steam可全额退款...
  9. 2022-2028全球肿块破碎机行业调研及趋势分析报告
  10. 如何判断一组数据是否符合正态分布呢?