c语言游戏实战(3):三子棋

前言:

三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏规则是双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利。但因棋盘太小,三子棋在很多时候会出现和棋的局面。

设计思路:

先开一个test.c文件用来进行游戏的逻辑测试,再开一个game.h头文件和game.c文件分别用来进行函数声明和实现游戏的逻辑,然后就是打印菜单、生成棋盘、实现玩家下棋、实现电脑下棋、判断游戏的输赢、游戏优化。

1. 打印菜单

test.c

void menu()
{printf("***************************\n");printf("********   1.play  ********\n");printf("********   2.exit  ********\n");printf("***************************\n");
}int main()
{int input = 0;do{menu();printf("请选择>:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏.\n");break;default:printf("输入有误,请重新输入.\n");}} while (input);return 0;
}

2. 生成棋盘

2.1 初始化棋盘

我们可以用空格将每一个格子初始化。

test.c文件:

board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);

 game.c文件:

void InitBoard(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] = " ";}}
}

其中的ROW和COL是两个宏定义。

 game.h

#define ROW 3
#define COL 3

2.2 打印棋盘

打印棋盘时我们可以一些符号隔开不同的空格,这样就会使我们的棋盘更加美观。比如我们可以使用“|”将同一行的空格分开,用“-”将不同行的空格分开,这样我们就可以得到一个如下的九宫格了。

 

 game.c文件:

void DisplayBoard(char board[ROW][COL], int row, int col)
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){printf("   ");if (j < col - 1){printf("|");}}printf("\n");if (i < row - 1){for (int j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}}
}

 3. 实现玩家下棋和电脑下棋

为了游戏的可实行性,当玩家或电脑下完一个棋子后我们需要考虑以下两点:

1.玩家或电脑所下的坐标是否在棋盘的范围内。

2.玩家或电脑所下的位置是否已经被下过棋子了。

依据上面的两点条件的我们需要分别写一个条件语句,判断玩家是否合法下棋。

3.1 玩家下棋

game.c文件:

void PlayerMove(char board[ROW][COL], int row, int col)
{int x = 0, y = 0;printf("玩家下棋:\n");while (1){printf("请输入你要落子的坐标:");scanf("%d%d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("输入的坐标已被占用,请重新输入\n");}}else{printf("坐标非法,请重新输入\n");}}
}

3.2 电脑下棋

思路: 

我们可以在让电脑生成随机数,这样就可以使其随机生成一个坐标下棋子,那么我们就可以简单的实现电脑下棋的效果了。

随机数的生成则可以使用rand函数、srand函数以及time函数。

game.c文件:

void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑下棋:>\n");while (1){int x = rand() % row;int y = rand() % row;if (x <= row && x >= 1 && y <= row && y >= 1){if (board[x][y] == ' '){board[x][y] = '#';break;}}}
}

test.c文件:

srand((unsigned int)time(UNLL))

game.h文件:

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

为了实现玩家下一个棋,然后电脑下一个棋的功能我们还需加上一个while循环。如下:

test.c文件:

while(1)
{//玩家下棋PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//电脑下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);
}

 4. 判断游戏的输赢

 思路:

此游戏无非只有三种结果:要么玩家赢,要么电脑赢,要么平局。所以我们可以写一个函数判断是这几种结果的哪一种,然后规定如果是玩家赢此函数返回“*”,如果是电脑赢则返回“#”,平局则返回“Q”,这几种都不是就说明游戏继续,那么就返回“C”.

要判断是否有赢的一方,无非就是判断是否出现了三个相同的棋子练成一条直线,而棋子连成的线无非就只有三种情况:竖线、横线、对角线。所以我们只需要判断是否出现了这三种情况的其中一种就可以了。而要判断是平局,则判断九宫格是否还有没有空格。

game.c文件:

int ItFull(char board[ROW][COL], int row, int col)
{for (int i = 0; i < row; i++){for (int j = 0;j < col; j++){if (board[i][j] == ' '){return 0;}}}return 1;
}
char ItWin(char board[ROW][COL], int row, int col)
{//行for (int i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')return board[i][1];}//列for (int j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')return board[1][j];}//对角线if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0){return board[1][1];}if (ItFull(board, row, col)){return 'Q';}return 'C';
}

test.c文件:

	//玩家下棋PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//判断输赢char ret = ItWin(board, ROW, COL);if (ret != 'C'){if (ret == '*'){printf("玩家赢了!!!\n");}break;}//电脑下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//判断输赢ItWin(board, ROW, COL);if (ret != 'C'){if (ret == '#'){printf("电脑赢了!!!\n");}break;}

完整代码:

game.h文件:


#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ROW 3
#define COL 3void InitBoard(char board[ROW][COL],int row,int col);void DisplayBoard(char board[ROW][COL], int row, int col);void PlayerMove(char board[ROW][COL], int row, int col);void ComputerMove(char board[ROW][COL], int row, int col);char ItWin(char board[ROW][COL], int row, int col);

test.c文件:

#include"game.h"void menu()
{printf("***************************\n");printf("********   1.play  ********\n");printf("********   2.exit  ********\n");printf("***************************\n");
}
void game()
{//第一步打印棋盘。char board[ROW][COL] = { 0 };//初始化棋盘InitBoard(board, ROW, COL);//打印棋盘DisplayBoard(board, ROW, COL);char ret;while(1){//玩家下棋PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//判断输赢char ret = ItWin(board, ROW, COL);if (ret != 'C'){if (ret == '*'){printf("玩家赢了!!!\n");}break;}//电脑下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//判断输赢ItWin(board, ROW, COL);if (ret != 'C'){if (ret == '#'){printf("电脑赢了!!!\n");}break;}}
}
int main()
{srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请选择>:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏.\n");break;default:printf("输入有误,请重新输入.\n");}} while (input);return 0;
}

game.c文件:

#include"game.h"void InitBoard(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] = ' ';}}
}void DisplayBoard(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 - 1)printf("|");}printf("\n");if (i < row - 1){for (int j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}}
}void PlayerMove(char board[ROW][COL], int row, int col)
{int x = 0, y = 0;printf("玩家下棋>:\n");while (1){printf("请输入你要落子的坐标:");scanf("%d%d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("输入的坐标已被占用,请重新输入\n");}}else{printf("坐标非法,请重新输入\n");}}
}void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑下棋:>\n");while (1){int x = rand() % row;int y = rand() % row;if (x <= row && x >= 1 && y <= row && y >= 1){if (board[x][y] == ' '){board[x][y] = '#';break;}}}
}int ItFull(char board[ROW][COL], int row, int col)
{for (int i = 0; i < row; i++){for (int j = 0;j < col; j++){if (board[i][j] == ' '){return 0;}}}return 1;
}
char ItWin(char board[ROW][COL], int row, int col)
{//行for (int i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')return board[i][1];}//列for (int j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')return board[1][j];}//对角线if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0){return board[1][1];}if (ItFull(board, row, col)){return 'Q';}return 'C';
}

运行图:

游戏优化: 

让电脑生成一个数的方式来实现一个电脑下棋的效果,肯定是没有什么可玩性的,等后面学习算法之后,我们就加入一些算法将其变为一个棋艺高超的棋手了。

以上就是使用c语言写三子棋的全部内容啦,如果上述内容对你有帮助的话不要忘记点上一个小小的赞和关注呦,期待我们下次再见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/334926.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【记录】网络|没有路由器没有网线,分别使用手机或Windows电脑共享网络给ARM64开发板,应急连接

事情是这样的&#xff0c;我的开发板明明已经选择了记住热点 WiFi 密码&#xff0c;但是却没有在开机的时候自动连接&#xff0c;我又没有放显示器在身边&#xff0c;又不想为了这点事去找个显示器来&#xff0c;就非常难受。 我手边有的设备是&#xff1a; 笔记本电脑&#…

蓝桥杯物联网竞赛_STM32L071_18_长短按键检测

长短按键的检测是国赛题里面遇到的&#xff0c;省赛没出过有两种实方法 定时器配置&#xff1a; 定时器的话要比delay准确&#xff0c;其中tim7定时器的准度最高 定时器预分配配置32 - 1&#xff0c;计数周期是10000 - 1这样做那么32MHZ/32也就是一秒钟记录10^6的数&#xf…

重置服务器之后 SSH 登录报错:REMOTE HOST IDENTIFICATION HAS CHANGED!

问题原因&#xff1a; 报错是由于远程的主机的公钥发生了变化导致的。ssh服务是通过公钥和私钥来进行连接的&#xff0c;它会把每个曾经访问过计算机或服务器的公钥&#xff08;public key&#xff09;&#xff0c;记录在~/.ssh/known_hosts 中&#xff0c;当下次访问曾经访问…

【机器学习300问】102、什么是混淆矩阵?

一、混淆矩阵的定义 混淆矩阵是一种用于评估分类模型性能的评估指标。当模型对数据进行预测并将数据分配到预定义的类别时&#xff0c;混淆矩阵提供了一种直观的方式来总结这些预测与数据实际类别之间的对应关系。具体来说&#xff0c;它是一个表格。 二、分类模型性能评估一级…

[AIGC] Nginx常用变量详解

Nginx非常强大&#xff0c;其主要功能包括HTTP服务器、反向代理、负载均衡等。Nginx的配置中有许多内置的变量&#xff0c;你可以在配置文件中使用这些变量进行灵活的配置。在本篇文章中&#xff0c;我们将介绍一些Nginx中常见的变量&#xff0c;包括proxy_add_header。 常见变…

【windows】Total Uninstall:一款功能强大的完全卸载软件

软件介绍 Total Uninstall是一款专业的软件卸载工具&#xff0c;旨在帮助用户彻底地清除计算机上的应用程序&#xff0c;包括与应用程序相关的所有文件和注册表项。以下是Total Uninstall的一些主要功能和特点&#xff1a; 完全卸载&#xff1a;软件可以监视应用程序的安装过程…

Linux-CentOS7-解决vim修改不了主机名称(无法打开并写入文件)

Linux-CentOS7-修改主机名称 修改之后使用强制保存退出也不行。 解决办法&#xff1a; 使用hostnamectl命令进行修改 查看系统主机名和信息&#xff1a; hostnamectl这条命令会显示当前系统的主机名、操作系统信息、内核版本、架构信息等相关信息。 修改系统主机名&#xff1…

行为设计模式之状态模式

文章目录 概述定义结构图 2.代码示例小结 概述 定义 状态模式(state pattern)的定义: 允许一个对象在其内部状态改变时改变它的行为。 对象看起来似乎修改了它的类。 状态模式就是用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题.。状态模式将一个对象的状态…

免费插件集-illustrator插件-Ai插件-文本对象分行

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件&#xff0c;加强illustrator使用人员工作效率&#xff0c;进行文本对象分行。首先从下载网址下载这款插件 https://download.csdn.net/download/m0_67316550/87890501&…

ubuntu-24.04系统静态Mac和IP配置

操作系统版本&#xff08;桌面版&#xff09;&#xff1a;ubuntu-24.04-desktop-amd64.iso 原因说明&#xff1a;因网络的IP地址和Mac是预分配的&#xff0c;所以ubuntu系统需要修改网卡的mac地址和IP才能访问&#xff0c;网络查了半天资料都没成功&#xff0c;后再界面提示&a…

IC618 虚拟机 EDA Calibre2019 Hspice2018 Spectre19.1

虚拟机包含 CentOS 7.9 Cadence IC618 Calibre 2019 Hspice 2018 Spectre19.1 下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1aMtPO2G5ad-x5BtIJjCDig?pwdxcii 提取码&#xff1a;xcii

【代码随想录】面试常考类型之动态规划01背包

前言 更详细的在大佬的代码随想录 (programmercarl.com) 本系列仅是简洁版笔记&#xff0c;为了之后方便观看 不同的二叉搜索树 96. 不同的二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 通过举例子发现重叠子问题 代码很简单&#xff0c;主要是思路问题&#xff0…

FaceChain-FACT:开源10秒写真生成,复用海量LoRa风格,基模友好型写真应用

github开源地址&#xff1a;https://github.com/modelscope/facechain/tree/main/facechain_adapter 魔搭创空间应用体验&#xff1a;魔搭社区 一、效果演示 FaceChain FACT的代码和模型目前已经在github和modelscope创空间上同步开源。FaceChain FACT具有简单的交互式界面设…

CentOS 7如何使用systemctl管理应用

说明&#xff1a;本文介绍如何使用systemctl命令的方式来启动、查看、停止和重启应用&#xff0c;以安装后的prometheus、alertmanager为例&#xff1b; Step1&#xff1a;创建文件 在系统/etc/systemd/system/路径下&#xff0c;创建一个xxx.service文件&#xff0c;该文件内…

UDP网络聊天室(更)

服务器端 #include <header.h> typedef struct node {char name[20];struct sockaddr_in cli_addr;struct node *next; }node,*node_p; typedef struct msg {char type;char name[20];char text[128]; }msg; node_p create_link() {node_p H(node_p)malloc(sizeof(node)…

C++ 数据类型

一 数据类型 数学中的数据类别 不同的性质&#xff1b; 不同的运算&#xff1b; 计算机中的数据类型 不同的表示形式 不同的存储空间 不同的运算 1 整数 注意 关于不同类型的数所占的字节数 C 没有规定不同类型的数占的字节数会因计算机系统、编译器的不同而不同sizeof()运算…

Trie字符串统计-java

Trie&#xff0c;又称前缀树或字典树&#xff0c;是一种有序树&#xff0c;用于保存关联数组&#xff0c;其中的键通常是字符串。 目录 前言☀ 一、Trie字符串统计☀ 二、算法思路☀ 1.Trie树定义&#x1f319; 2.变量解释&#x1f319; 3.插入操作&#x1f319; 4.Trie树查找操…

【算法】位运算算法——丢失的数字

题解&#xff1a;丢失的数字(位运算算法) 目录 1.题目2.题解3.位运算异或4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 哈希数组查漏高斯求和排序位运算异或… 3.位运算异或 class Solution { public:int missingNumber(vector<int>& nums) {int ret 0;for…

动态规划之买卖股票大集合

目录 引言 1.只能进行一次买卖股票&#xff08;最多只能买一股股票&#xff09; 2.可以进行多次股票买卖&#xff0c;且没有手续费&#xff08;最多只能买一股股票&#xff09; 3.可以进行多次股票买卖&#xff0c;但是有冷冻期&#xff0c;无手续费&#xff08;最多只能买一…

电脑卡顿---WINDOWS任何关闭应用开机自启动

打开windows11的控制面板&#xff0c;点击应用&#xff0c;点击启动 如下图圈出来的地方就是开机自启动的开关按键。