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

2024-04-08 14:04
文章标签 语言 实战 游戏 三子

本文主要是介绍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语言写三子棋的全部内容啦,如果上述内容对你有帮助的话不要忘记点上一个小小的赞和关注呦,期待我们下次再见。

这篇关于c语言游戏实战(3):三子棋的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/885792

相关文章

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA