当前位置: 首页 > news >正文

C语言编写三子棋游戏:从概念到思路到实现

目录

一.文章概述

二.游戏规则概述

三.理解思路

1. 定义游戏数据结构

2. 游戏搭建思路及其步骤

·菜单选择列表:

·初始化棋盘:所有位置均为空格

·创建棋盘样式

·设置玩家下棋

·设置电脑下棋

·检查游戏状态:

四.代码示例

一.game.c部分

二.game.h部分

三.test.c部分

结论


一.文章概述

本文将深入探讨用C语言实现一个经典的双人策略游戏——三子棋(Tic Tac Toe)。我们不仅会详细解释游戏规则、数据结构选择,还会阐述如何设计和编码游戏的逻辑流程。通过本篇文章,读者能够理解如何从概念分析到具体代码实现,一步步构建出完整的三子棋游戏。

二.游戏规则概述

三子棋是一种经典的两人策略游戏,通常在一个3x3(本次代码可以随意更改棋盘大小)的网格上进行。玩家轮流放置他们的标记(这里代码玩家下棋用“*”,电脑下棋用“#”来示例),目的是在横行、竖列或斜对角线上获得三个连续的标记及为获胜。

1.一个玩家形成一条直线上的三个标记。

2.所有的格子都被占用(平局)。

三.理解思路

1. 定义游戏数据结构

创建一个二维数组来表示棋盘。使用字符型数组 

//存放数据需要一个3*3的二维数组char board[ROW][COL] = {0};

 来存储每个位置的棋子,其中 ‘’, ‘*’, 和 ‘#’分别代表空位、玩家和电脑。

2. 游戏搭建思路及其步骤

·菜单选择列表

//声明菜单是menu定义格式
void menu()
{printf("*******************************\n");printf("********    1. play      ******\n");printf("********    0. exit      ******\n");printf("*******************************\n");
}

·初始化棋盘:所有位置均为空格

//初始化棋盘InitBoard(board, ROW, COL);
//方法一
void InitBoard(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){board[i][j] = ' ';}}
}
//方法二
void InitBoard(char board[ROW][COL], int row, int col)
{memset(&board[0][0], ' ', row*col*sizeof(board[0][0]));
}

·创建棋盘样式

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

·设置玩家下棋

使用循环结构(如 while 循环)来处理玩家和电脑输入,询问玩家和电脑选择的位置并验证。通常需要一个函数来接受用户输入的行和列,并转换为有效的数组索引。

//判断玩家下棋输入坐标是否符合要求
//若符合要求,则判断该位置是否是没有超出棋盘范围的
//若没有超出且该位置是空的,玩家就下棋
//为了能达成赢,输,平局三种其一的局面
//需要while不停的循环
void PlayerMove(char board[ROW][COL], int row, int col)
{int x = 0;int 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)
{int x = 0;int y = 0;printf("电脑下棋>:\n");while (1){//假如row=9//rand()%row=0-8//那么+1就是1-9x = rand() % row;y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}}
}

·检查游戏状态

需要有函数来检查游戏是否结束(是否有胜者或平局)和验证下棋操作的有效性(确保不是重复落子、非空位等)。

//判断输赢
//玩家赢 - '*'
//电脑赢 - '#'
//平局   - 'Q'
//继续   - 'C'char IsWin(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){//判断行if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' '){return board[i][0];}}for (i = 0; i < col; i++){//判断列if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' '){return board[0][i];}}if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){//判断主对角线//不是必须返回对角线的中心//中心是更好的理解代码含义//也是代码的整洁性//简洁的代码理解效率更高return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){//判断副对角线return board[1][1];}//判断是否平局if (IsFull(board, row, col)){return 'Q';}//游戏继续return 'C';
}int IsFull(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){//判断平局关键就是//当格子没有是空的时候if (board[i][j] == ' '){//没有空格子了就直接返回0终止程序return 0;}}}//继续下棋return 1;
}

四.代码示例

一.game.c部分

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"void InitBoard(char board[ROW][COL], int row, int col)
{int i,j;//方法一//for (i = 0; i < row; i++)//{//	for (j = 0; j < col; j++)//	{//		//刚开始棋盘上是什么都没有的//		board[i][j]=' ';//	}//}//方法二  包含头文件#include "string.h"//函数规定将&/*部分指向的地方前多大空间转化为空格(' ')memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));}//void DispalyBoard(char board[ROW][COL], int row, int col)
//{
//	int i, j;
//
//	for (i = 0; i < row; i++)
//	{
//		//写死了只能打印3列
//		printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);
//		if (i < row - 1)
//		{
//			printf("---|---|---\n");
//		}
//	}
//
//}void DispalyBoard(char board[ROW][COL], int row, int col)
{int i, j;//灵活变换的棋盘for (i = 0; i < row; i++){//把一个字符和一个竖杠看作一组//---|---|---//那么最后一组没有‘|’//先打印数据和|for (j = 0; j < col; j++){printf(" %c ",board[i][j]);if (j < col - 1){printf("|");}}printf("\n");//再打印---分割上下部分if (i < row - 1){for (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;int 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)
{int x = 0;int y = 0;printf("电脑下棋:>\n");//随机函数while (1){x = rand() % row;y = rand() % col;if (board[x][y] = ' '){board[x][y] = '#';break;}}
}//判断棋盘是否满了
int Is_Full(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' '){return 0;}}}return 1;
}//判断输赢
//玩家赢 - '*'
//电脑赢 - '#'
//平局   - 'Q'
//继续   - 'C'
char IsWin(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){//判断行是否连起来if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' '){return board[i][0];}}//判断列for (i = 0; i < col; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' '){return board[0][i];}}///判断主副对角线//为什么要是board[1][1] != ' ',board[0][0] != ' '不可以吗,前面不都是判断了board[1][1] ==board[0][0]//因为他是中间相互公共部分,是00或者22的话//意思就是如果要改的话,主副对角线就要检查对角位置就可以了,用中心检查是为了提高代码效率而已if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[1][1];}//判断平局if (Is_Full(board, row, col)){return 'Q';}return 'C';
}

二.game.h部分

#pragma once//头文件的包含
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define ROW 3
#define COL 3//函数的声明//初始化棋盘
void 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 IsWin(char board[ROW][COL],int row, int col);

三.test.c部分

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"void menu()
{printf("***** 请    选    择 *****\n");printf("***** 1.play  0.exit *****\n");printf("**************************\n");
}void game()
{//如果是这样的话,确实打印出了棋盘//但是直接打印的话那么如何落子输入?/*printf("  |  |  \n");printf("--|--|--\n");printf("__|__|__\n");printf("  |  |  \n");*///运用数组解决问题//存放一个3*3的数组char board[ROW][COL] = { 0 };char ret = 0;//初始化棋盘InitBoard(board, ROW, COL);//打印棋盘DispalyBoard(board, ROW, COL);while (1){//下棋//玩家下PlayerMove(board, ROW, COL);//打印DispalyBoard(board, ROW, COL);//判断输赢ret=IsWin(board, ROW, COL);if (ret != 'C'){//在这里不判断谁赢//当不平局直接跳出,再进行判断//节省了代码break;}//电脑下ComputerMove(board, ROW, COL);//打印DispalyBoard(board, ROW, COL);//判断输赢ret = IsWin(board, ROW, COL);if (ret != 'C'){break;}}if ('*' == ret){printf("玩家赢\n");}else if ('#' == ret ){printf("电脑赢\n");}else if ('C' == ret){printf("平局\n");}}int main()
{int input=0;srand((unsigned int)time(NULL));//这个循环是为了能一直输入选择并且完成任务do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请请重新选择\n");break;}} while(input);return 0;
}

结论

这个简单的C语言程序实现了三子棋的基本功能:定义游戏数据结构、游戏搭建思路及其步骤、检查胜利条件和切换玩家等。使用标准输入输出函数进行人机交互,并通过数组来管理棋盘状态。


我期待这篇博客示例能为你提供宝贵的思路和指导,在使用C语言构建三子棋游戏的过程中遇到问题时找到有效的解决方案。在这段旅程中,请记住,正确地挑选并应用合适的函数是关键所在——这一点在实际编程过程中尤为重要。通过合理选择这些功能,你可以确保程序不仅高效而且易于维护。希望这个资源能成为你编程之旅中的得力助手,并激发你进一步探索和优化代码的热情。

http://www.lryc.cn/news/429898.html

相关文章:

  • React.js如何使用Bootstrap
  • 深入解析:Redis与Nacos分布式锁在业务中的具体应用
  • MySQL索引的性能优化
  • 协方差详解及在日常生活中的应用实例——天气温度与冰淇淋销量的关系
  • Spring Boot3.3.X整合Mybatis-Plus
  • 快速了解软件测试——测试用例的方法
  • 多线程、多进程,还是异步?-- Python 并发 API 如何选择
  • 汽车服务管理系统 _od8kr
  • 带你玩转小程序推广,实现短链接一键跳转
  • OpenDDS的Rtps_Udp传输协议可靠性QoS收发基本流程
  • 体育数据API纳米奥运会数据API:高阶数据包接口文档API示例⑦
  • 【中项第三版】系统集成项目管理工程师 | 第 15 章 组织保障
  • 数据结构——顺序栈和链式栈
  • PHP轻创推客集淘客地推任务平台于一体的综合营销平台系统源码
  • three.js实现 加载3dtiles ,瓦片 ,倾斜摄影,功能
  • Qt QTextEdit调用append数据重复的问题
  • 数学基础(二)
  • Java设计模式原则及中介者模式研究
  • logstash入门学习
  • 【代码】Swan-Transformer 代码详解(待完成)
  • iframe.contentDocument 和document.documentElement的区别
  • 计算机操作员试题(中篇)
  • 车规级MCU「换道」竞赛
  • 数学生物学-2-离散时间模型(Discrete Time Models)
  • 免费开源!AI视频自动剪辑已成现实!效率提升80%,打工人福音!(附详细教程)
  • NtripShare全站仪自动化监测之气象改正
  • 【人工智能】项目案例分析:使用自动编码器进行信用卡欺诈检测
  • 【工控】线扫相机小结
  • 将Web应用部署到Tomcat根目录的三种方法
  • 工业和信息化部教育与考试中心计算机相关专业介绍