热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

井字棋小游戏

目录前言一、主要思路二、菜单栏和其他安排三、game函数的实现小函数定义1.init_board函数初始化棋盘全为空格2.disp_baord函数打印棋盘3.pla

 

目录

前言

一、主要思路

二、菜单栏和其他安排

三、game函数的实现

小函数定义

1. init_board函数初始化棋盘全为空格

2. disp_baord函数打印棋盘

3. player_move函数 玩家下棋

4. computer_move函数 电脑随机下棋

5. is_win函数 判断游戏是否结束

game函数定义

总结






前言

设计一个井字棋游戏,玩家操作符号:*    电脑操作符号:o

先串连三颗棋子的棋手获胜(故又称三子棋)。

此程序可重复进行游戏。




一、主要思路

1.先打印一个菜单栏,让玩家选择开始游戏或者退出游戏。

2.然后用一个switch语句,进行各种选项的分支。

玩家选择 1,进入game函数,开始游戏。

3.game函数:

初始化棋盘,并打印。

玩家和电脑轮流下棋,并打印出棋盘供玩家分析。

棋手每下一步,判断游戏是否结束。

4.结束后再次打印菜单栏,让玩家选择是否继续游戏。

 


二、菜单栏和其他安排

    菜单栏:直接按照下图的代码打印。

    定义行row为3,列col为3。以后根据需要,可以在此更改行数和列数,将三子棋扩展成四子棋,五子棋等。

  将该项目分成三个文件:头文件声明函数,game.c文件定义函数,yaun.c文件测试游戏。

 

 




三、game函数的实现


小函数定义


1. init_board函数初始化棋盘全为空格

    两个for循环,初始化row行、col列的棋盘为空格 ' '。

void init_board(char arr[row][col])
{//棋盘初始化:全为空int i = 0, j = 0;for (i = 0; i }

2. disp_baord函数打印棋盘

打印col行,rol列的棋盘。

棋盘每行:

( 1 ) 每列(col-1列)打印空格+棋格内容+空格+分隔竖 |(棋盘线),第col列不打印棋盘线;

   ( 2 ) 每列(col-1列)打印三个下划线___+一个分割竖线 | 当做棋盘线,最后一列无分割竖线;

   ( 3 )   最后一行只操作(1)不操作(2)。

void disp_baord(char arr[row][col])
{int i = 0, j = 0;for (i = 0; i }


3. player_move函数 玩家下棋

   玩家输入两个数作为棋盘棋盘坐标,同时也是存放棋格的数组下标+1;

   需要注意的是,如果棋格已被占有(该位置数组元素不为空格),应该提醒玩家下错了,要重新落子。

void player_move(char arr[row][col])
{int x &#61; 0,y &#61; 0; //x,y为棋盘坐标&#xff1b;while (1){scanf("%d%d", &x, &y);if (x > 0 && x <&#61; 3 && y > 0 && y <&#61; 3){if (arr[x - 1][y - 1] &#61;&#61; &#39; &#39;){arr[x - 1][y - 1] &#61; &#39;*&#39;;break;}else{printf("该位置已有棋子&#xff0c;请重新放置\n");}}elseprintf("放置位置越界&#xff0c;请重新放置\n");}
}


4. computer_move函数 电脑随机下棋

     srand函数放在主函数里边&#xff0c;computer_move函数定义时可用rand函数%行&#xff0c;或者rand函数%列&#xff0c;得到相应的数组下边&#xff0c;并在该数组下标对应的棋盘坐标落子&#xff08;即把数字里的空格换成电脑棋子符号 o&#xff09;。如果随机坐标下已有棋子&#xff08;对应数组不为空格&#xff09;&#xff0c;重新获取随机值。

void computer_move(char arr[row][col])
{int x &#61; 0, y &#61; 0; //x,y为数组下标&#xff0c;&#43;1为棋盘坐标while (1){x &#61; rand() % row; // 0-2y &#61; rand() % col; //生成随机坐标 0-2if (arr[x][y] &#61;&#61; &#39; &#39;){arr[x][y] &#61; &#39;o&#39;;break;}}
}


5. is_win函数 判断游戏是否结束

     如果某种棋子符号 行串连/ 列串连/ 对角线串连 &#xff0c;则对应棋手获胜&#xff0c;返回该棋子符号。 

     num为传入的步数&#xff0c;棋盘一共可以走sum&#61;row*col 步。走完后&#xff08;num&#61;&#61;sum&#xff09;&#xff0c;还未分出胜负则视为平局&#xff0c;返回&#39;D&#39;。(deuce,平局)

    两者都不符合&#xff0c;证明棋局还在继续&#xff0c;返回&#39;C&#39;。&#xff08;continue,继续&#xff09;

char is_win(char arr[row][col],int num)
{int i &#61; 0;int sum &#61; row * col;for (i &#61; 0; i }

game函数定义

&#xff08;1&#xff09;初始化棋盘为空格

&#xff08;2&#xff09;打印空气盘

&#xff08;3&#xff09;进入下棋模式&#xff08;while循环&#xff09;&#xff1a;

       玩家一步&#xff0c;打印棋盘。判断是否结束&#xff0c;结束则跳出循环。

       电脑一步&#xff0c;打印棋盘。判断是否结束&#xff0c;结束则跳出循环。

&#xff08;4&#xff09;根据is_win返回值判断游戏胜负或者平局。

void game()
{char ret &#61; 0;int num &#61; 0; //步数srand((unsigned int)time(NULL));char board[row][col] &#61; { 0 };init_board(board); //初始化棋盘disp_baord(board); //打印棋盘while (1){//玩家下棋num&#43;&#43;;printf("玩家下棋&#xff1a;\n");player_move(board);disp_baord(board); //下一次棋打印一次棋盘printf("\n");ret &#61; is_win(board, num); // *玩家获胜&#xff1b;o电脑获胜&#xff1b;C继续游戏&#xff1b;D平局if (ret !&#61; &#39;C&#39;) //判断是否继续{break;}//电脑下棋num&#43;&#43;;computer_move(board);printf("电脑下棋&#xff1a;\n");disp_baord(board);printf("\n");ret &#61; is_win(board, num);if (ret !&#61; &#39;C&#39;) //判断是否继续{break;}}// 出现胜负 if (ret &#61;&#61; &#39;*&#39;){printf("玩家获胜\n\n");}else if (ret &#61;&#61; &#39;o&#39;){printf("电脑获胜\n\n");}else{printf("平局\n\n");}
}


总结

该程序的不足之处在于电脑下棋是随机的&#xff0c;电脑并不具备一定水平的棋术。

以下是三个文件的全部代码&#xff1a;

头文件:

#define row 3
#define col 3
#include
#include
#include
void init_board(char arr[row][col]);
void disp_baord(char arr[row][col]);
void computer_move(char arr[row][col]);
void player_move(char arr[row][col]);
char is_win(char arr[row][col],int num);

game.c文件&#xff1a;

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void init_board(char arr[row][col])
{//棋盘初始化&#xff1a;全为空int i &#61; 0, j &#61; 0;for (i &#61; 0; i }
void disp_baord(char arr[row][col])
{int i &#61; 0, j &#61; 0;for (i &#61; 0; i }
void computer_move(char arr[row][col])
{int x &#61; 0, y &#61; 0; //x,y为数组下标&#xff0c;&#43;1为棋盘坐标while (1){x &#61; rand() % row; // 0-2y &#61; rand() % col; //生成随机坐标 0-2if (arr[x][y] &#61;&#61; &#39; &#39;){arr[x][y] &#61; &#39;o&#39;;break;}}
}
void player_move(char arr[row][col])
{int x &#61; 0,y &#61; 0; //x,y为棋盘坐标&#xff1b;while (1){scanf("%d%d", &x, &y);if (x > 0 && x <&#61; 3 && y > 0 && y <&#61; 3){if (arr[x - 1][y - 1] &#61;&#61; &#39; &#39;){arr[x - 1][y - 1] &#61; &#39;*&#39;;break;}else{printf("该位置已有棋子&#xff0c;请重新放置\n");}}elseprintf("放置位置越界&#xff0c;请重新放置\n");}
}
char is_win(char arr[row][col],int num)
{int i &#61; 0;int sum &#61; row * col;for (i &#61; 0; i }

yuan.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{printf("**********************\n");printf("****** 1→ play ******\n"); printf("****** 0→ exit ******\n");printf("**********************\n");printf(" 请选择:> \n\n");
}
void game()
{char ret &#61; 0;int num &#61; 0; //步数srand((unsigned int)time(NULL));char board[row][col] &#61; { 0 };init_board(board); //初始化棋盘disp_baord(board); //打印棋盘while (1){//玩家下棋num&#43;&#43;;printf("玩家下棋&#xff1a;\n");player_move(board);disp_baord(board); //下一次棋打印一次棋盘printf("\n");ret &#61; is_win(board, num); // *玩家获胜&#xff1b;o电脑获胜&#xff1b;C继续游戏&#xff1b;D平局if (ret !&#61; &#39;C&#39;) //判断是否继续{break;}//电脑下棋num&#43;&#43;;computer_move(board);printf("电脑下棋&#xff1a;\n");disp_baord(board);printf("\n");ret &#61; is_win(board, num);if (ret !&#61; &#39;C&#39;) //判断是否继续{break;}}// 出现胜负 if (ret &#61;&#61; &#39;*&#39;){printf("玩家获胜\n\n");}else if (ret &#61;&#61; &#39;o&#39;){printf("电脑获胜\n\n");}else{printf("平局\n\n");}
}int main()
{int input &#61; 0;do{menu(); //打印菜单栏scanf("%d", &input); //玩家选择是否进行游戏switch (input){case 1:game(); //执行游戏函数break;case 0:printf("退出游戏\n");break;default:printf("选择错误&#xff0c;请重新选择\n");break;}} while (input); //结束一局后可再次palyreturn 0;
}

感谢您的阅读&#xff01;


推荐阅读
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • Linux环境下C语言实现定时向文件写入当前时间
    本文介绍如何在Linux系统中使用C语言编程,实现在每秒钟向指定文件中写入当前时间戳。通过此示例,读者可以了解基本的文件操作、时间处理以及循环控制。 ... [详细]
  • CSS高级技巧:动态高亮当前页面导航
    本文介绍了如何使用CSS实现网站导航栏中当前页面的高亮显示,提升用户体验。通过为每个页面的body元素添加特定ID,并结合导航项的类名,可以轻松实现这一功能。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 在尝试使用C# Windows Forms客户端通过SignalR连接到ASP.NET服务器时,遇到了内部服务器错误(500)。本文将详细探讨问题的原因及解决方案。 ... [详细]
  • 本文介绍了一种基于选择排序思想的高效排序方法——堆排序。通过使用堆数据结构,堆排序能够在每次查找最大元素时显著提高效率。文章详细描述了堆排序的工作原理,并提供了完整的C语言代码实现。 ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
  • 本文探讨了符号三角形问题,该问题涉及由相同数量的“+”和“-”符号组成的三角形。通过递归回溯法,可以有效地搜索并计算符合条件的符号三角形的数量。 ... [详细]
  • 探讨 HDU 1536 题目,即 S-Nim 游戏的博弈策略。通过 SG 函数分析游戏胜负的关键,并介绍如何编程实现解决方案。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • This post discusses an issue encountered while using the @name annotation in documentation generation, specifically regarding nested class processing and unexpected output. ... [详细]
  • 由二叉树到贪心算法
    二叉树很重要树是数据结构中的重中之重,尤其以各类二叉树为学习的难点。单就面试而言,在 ... [详细]
author-avatar
pea101
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有