C语言从0到1之《三子棋》的实现

news2024/11/26 18:33:46

 

🕺作者@启明星使

🎃专栏:《数据库》《C语言》

🏇分享一句话:

沉香:差一点,怎么总是差一点

杨戬:一定是练功的时候总是差不多,到了关键的时候就是差一点

大家一起加油🏄‍♂️🏄‍♂️🏄‍♂️

希望得到大家的支持,如果有帮助希望得到的大家三连~~~afbae359ff6c469aa4242bd6dcb5e558.jpeg

 

前言

新手小白想学好编程,一定要注重代码实现

所以今天我将带领大家写一个小游戏《三子棋》

需要具备的知识有循环·数组·函数

是不是都学过了呢?

那么我们来动手实操检验一下成果~~~

思路

  1. 首先我们要有个菜单,选择开始或者退出

  2. 我们要有个井字格来划分区域

  3. 我们要能下棋

  4. 电脑要和我们对局

  5. 要判断是否胜利

具体实现

菜单

void memu() {
    printf("********************************\n");
    printf("************* 1->开始 **********\n");
    printf("************* 0->退出 **********\n");
    printf("********************************\n");
    printf("->");
}

这里我们用到printf打印一个界面

接下来就要输入1或者0来选择

是不是非常简单,我们接着往下看~

主函数

一个switch语句进行选择

int main() {
    memu();
    srand((unsigned int)time(NULL));//电脑随机下棋,后续会有解释
    int input;
    scanf("%d", &input);
    switch(input) {
    case 0:
        exit(0);//强制退出程序
        break;
    case 1:
        game();//后续接着进入游戏
        break;
    default:
        printf("输入错误!");
        break;
    }
​
}
 

初始化数组

我们要使用一个char型数组来存储棋子

先将数组初始化

void Init(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为列

void print(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");
        }
    }
}

接下来我们就要开始下棋了

tip:玩家为* 电脑为#

玩家先手

这里我们要考虑几个问题:

  1. 输入的坐标并不是数组的下标

  2. 输入坐标超过数组的界限怎么办

void player_move(char board[ROW][COL], int row, int col) {
    while (1)
    {
        printf("请输入要下棋的坐标:>");
        int x = 0;
        int y = 0;
        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 is_full(char board[ROW][COL], int row, int col) {
    int flag = 0;
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            if (board[i][j] == ' ') {
                flag++;
            }
        }
    }
    if (flag == 0) {
        printf("平局\n");
        exit(0);
    }
}

电脑对局

在这里我们用随机数的方式实现电脑下棋

void computer_move(char board[ROW][COL], int row, int col) {
    printf("AI下棋:\n");
    while (1) {
        is_full(board, ROW, COL);
        int x = rand() % row;
        int y = rand() % col;
        //使用rand()函数
        //之前我们使用srand((unsigned int)time(NULL))
        //就是以时间来求随机数以求更随机
        if (board[x][y] == ' ') {
            board[x][y] = '#';
            break;
        }
    }
}

判断胜负

三子棋的规则是什么?

三个相同的棋在同行同列或者对角线上即为胜利

char is_win(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][0] != ' ')
        {
            return board[i][0];
        }
    }
    for (int 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];
    }
    is_full(board, ROW, COL);
}

这里我们返回符合条件的*或者#,在game()函数中判断返回值,即可判断胜利

game()函数

使用一个循环,如果有一方胜利或者平局则打破循环结束游戏

void game() {
    char board[ROW][COL];
    char res = 0;
    Init(board, ROW, COL);
    print(board, ROW, COL);
    while (1) {
        player_move(board, ROW, COL);
        print(board, ROW, COL);
        is_win(board, ROW, COL);
        Sleep(1000);
        computer_move(board, ROW, COL);
        print(board, ROW, COL);
        is_win(board, ROW, COL);
        res= is_win(board, ROW, COL);
        if (res == '*') {
            printf("玩家胜!\n");
            break;
        }
        else if(res=='#') {
            printf("AI胜!\n");
            break;
        }
    }
}

 

总结

在写代码的过程中,遇到问题解决问题是提升最快的方式。

当你碰到不会的,不懂的,不要害怕,这正是你所能够进步的地方!

我是分模块写的,源码如下:

fun.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "sanziqi.h"
void memu() {
	printf("********************************\n");
	printf("************* 1->开始 **********\n");
	printf("************* 0->退出 **********\n");
	printf("********************************\n");
	printf("->");
}

void game() {
	char board[ROW][COL];
	char res = 0;
	Init(board, ROW, COL);
	print(board, ROW, COL);
	while (1) {
		player_move(board, ROW, COL);
		print(board, ROW, COL);
		is_win(board, ROW, COL);
		Sleep(1000);
		computer_move(board, ROW, COL);
		print(board, ROW, COL);
		is_win(board, ROW, COL);
		res= is_win(board, ROW, COL);
		if (res == '*') {
			printf("玩家胜!\n");
			break;
		}
		else if(res=='#') {
			printf("AI胜!\n");
			break;
		}
	}
}
void Init(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 print(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 player_move(char board[ROW][COL], int row, int col) {
	while (1)
	{
		printf("请输入要下棋的坐标:>");
		int x = 0;
		int y = 0;
		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 computer_move(char board[ROW][COL], int row, int col) {
	printf("AI下棋:\n");
	while (1) {
		is_full(board, ROW, COL);
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ') {
			board[x][y] = '#';
			break;
		}
	}
}
char is_win(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][0] != ' ')
		{
			return board[i][0];
		}
	}
	for (int 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];
	}
	is_full(board, ROW, COL);
}
void is_full(char board[ROW][COL], int row, int col) {
	int flag = 0;
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			if (board[i][j] == ' ') {
				flag++;
			}
		}
	}
	if (flag == 0) {
		printf("平局\n");
		exit(0);
	}
}

main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "sanziqi.h"
int main() {
	memu();
	srand((unsigned int)time(NULL));
	int input;
	scanf("%d", &input);
	switch(input) {
	case 0:
		exit(0);
		break;
	case 1:
		game();
		break;
	default:
		printf("输入错误!");
		break;
	}

}

sanziqi.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 3
#define COL 3
void memu();//菜单
void game();//进入游戏
void Init(char board[ROW][COL], int row, int col);//初始化
void print(char board[ROW][COL],int row,int col);//打印界面
void player_move(char board[ROW][COL], int row, int col);//玩家下棋
void computer_move(char board[ROW][COL], int row, int col);//AI下棋
char is_win(char board[ROW][COL], int row, int col);//判断胜利
void is_full(char board[ROW][COL], int row, int col);//判断是否填满,平局

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android Studio开发之应用组件Application的讲解及实战(附源码,通过图书管理信息系统实战)

需要源码请点赞关注收藏后评论区留言~~ 一、Application的生命周期 Application是Android的一大组件&#xff0c;在APP运行过程中有且仅有一个Application对象贯穿应用的整个生命周期 打开AndroidMainfest.xml 发现activity节点的上级正是application节点&#xff0c;不过该节…

手把手带你搭建个人博客系统(一)

⭐️前言⭐️ 该web开发系统涉及到的知识&#xff1a; Java基础MySQL数据库JDBC技术前端三件套&#xff08;HTMLCSSJavaScript&#xff09;Servlet 使用到的开发工具&#xff1a; ideavscodetomcatpostmanFiddler 博主将会手把手带你搭建个人博客系统。 因文章篇幅较长&am…

【Spring boot 静态资源处理】

默认静态资源处理 Spring Boot 默认为我们提供了静态资源处理&#xff0c;使用 WebMvcAutoConfiguration 中的配置各种属性。 建议大家使用 Spring Boot 的默认配置方式&#xff0c;如果需要特殊处理的再通过配置进行修改。 如果想要自 己 完 全 控 制 WebMVC &#xff0c;就需…

快速创建django项目管理系统流程

首先创建django project&#xff0c;虚拟环境选择我已经有的虚拟环境&#xff0c;下面是创建后的画面&#xff0c;简单的框架模板&#xff0c;需要配置改动一些代码参数&#xff0c;才能适合我自己的习惯。 这里我经常用到的习惯必须导入的是simpleui库&#xff0c;还有django的…

基于STM32-Socket-Qt 遥控小车(一代)

文章目录一、项目分析1. 项目简介2. 知识储备3. 硬件选择二、STM32部分三、QT部分四、遥控小车演示程序源码一、项目分析 1. 项目简介 本项目本质为客户端与服务器之间的通信&#xff0c;通过发送不同的指令&#xff0c;服务器和客户端进行不同的操作。 客户端&#xff1a;基…

声学特征提取

声学特征提取流程图 语谱图 语谱图的横坐标是时间&#xff0c;纵坐标是频率&#xff0c;坐标点值为语音数据能量。由于是采用二维平面表达三维信息&#xff0c;所以能量值的大小是通过颜色来表示的&#xff0c;颜色深&#xff0c;表示该点的语音能量越强。 语谱图形成过程 …

zabbix监控Linux

1. 环境配置&#xff1a; 主机名主机地址操作系统角色zabbix192.168.188.201Rocky Linux release 8.6zabbix-servernode1192.168.188.111CentOS7zabbix-agent 2. 配置zabbix客户端&#xff1a; 1>. 下载并安装zabbix客户端&#xff1a; [rootnode1 ~]# wget https://mi…

Ubuntu 22.04安装Cuda11.7和cudnn

安装显卡驱动 打开‘软件和更新。 点击附加驱动安装显卡驱动 如果已经安装显卡驱动&#xff0c;请忽略上面的步骤。 安装gcc 新安装的Ubuntu22.04 没有安装gcc&#xff0c;需要安装gcc。在终端输入gcc -version 查看有没有gcc。 执行命令 sudo apt install gcc安装CUDA …

什么是蜂窝移动网络?

文章目录前言移动网络 vs WIFI蜂窝移动通信网蜂窝网络实现移动上网通信网架构总结前言 本博客仅做学习笔记&#xff0c;如有侵权&#xff0c;联系后即刻更改 科普&#xff1a; 移动网络 vs WIFI 计网课外实验月&#xff0c;我走在宿舍一楼正数着AP有多少个&#xff0c;突然W…

待业将近一个月,晚上11点接到面试邀约电话,我却拒绝了...

前言 一位测试朋友最近一直在找工作&#xff0c;前两天刚拒绝了一个面试。那天晚上11点多&#xff0c;他接到一个HR的面试电话&#xff0c;让他第二天早上10点去公司面试。朋友和HR聊了两句&#xff0c;了解到这位HR经常加班&#xff0c;于是果断拒绝了这个面试。我还为他可惜&…

LongAdder的源码学习与理解

&#x1f468;‍&#x1f4bb;个人主页&#xff1a; 才疏学浅的木子 &#x1f647;‍♂️ 本人也在学习阶段如若发现问题&#xff0c;请告知非常感谢 &#x1f647;‍♂️ &#x1f4d2; 本文来自专栏&#xff1a; Java基础 ❤️ 支持我&#xff1a;&#x1f44d;点赞 &#x1…

Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信)

运行有问题或需要源码请点赞关注收藏后评论区留言 一、利用ContentResolver读写联系人 在实际开发中&#xff0c;普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据&#xff0c;比如查看联系人&#xff0c;短信&#…

Linux top命令的cpu使用率和内存使用率

文章目录前言一、cpu使用率1.1 top简介1.2 cpu使用率的来源二、内存使用率2.1 总内存有关的数据2.2 进程使用内存有关的数据2.3 内存使用率的来源三、 pmap参考资料前言 NAMEtop - display Linux processes一、cpu使用率 1.1 top简介 top程序提供当前运行系统的动态实时视图…

网络协议:一文搞懂Socket套接字

本篇内容包括&#xff1a;Socket 套接字的简介、Socket 套接字的分类、Java 中的 Socket 即 java.net.ServerSocket、java.net.Socket 的使用&#xff0c;以及Java 使用套接字 Scoket 编程的Demo。 一、Socket 简介 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、…

Qt编写跨平台RTSP/RTMP/HTTP视频流播放器

一、前言 很早以前就做过这款播放器的入门版本&#xff0c;最开始用的ffmpeg去解析&#xff0c;后面陆续用vlc播放器、mpv播放器来做&#xff0c;毕竟播放器提供的接口使用也很方便&#xff0c;而且功能强大&#xff0c;后面发现播放器主要的应用场景是播放视频文件&#xff0…

安装配置Anaconda3

1.装anaconda&#xff0c;就不需要单独装python了 2、 下载Anaconda Anaconda | Anaconda Distribution 3、 安装Anaconda 其他默认 4、配置Anaconda环境变量 此电脑——属性——高级系统设置——环境变量——path——编辑——新建 C:\ProgramData\Anaconda3 C:\ProgramDa…

mybatis 自动化处理 mysql 的json类型字段 终极方案

文章目录mybatis 自动化处理 mysql 的json类型字段 终极方案mysql 建表 json 字段&#xff0c;添加1条json 数据对应的java对象 JsonEntitymybatis&#xff0c;不使用 通用mapper手动自定义1个类型处理器&#xff0c;专门处理 JsonNode 和Json 的互相转化将 自定义的类型处理器…

Java笔记(十二)

文献种类&#xff1a;专题技术总结文献 开发工具与关键技术&#xff1a; IntelliJ IDEA、Java 语言 作者&#xff1a; 方建恒 年级&#xff1a; 2020 撰写时间&#xff1a; 2022 年 11 月 8 日 Java笔记(十二) 今天我给大家继续分享一下我的Java笔记&#xff0c; 我们继续来了…

使用前缀和数组解决“区间和查询“问题

本文已收录到 GitHub AndroidFamily&#xff0c;有 Android 进阶知识体系&#xff0c;欢迎 Star。技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 进 Android 面试交流群。 前言 大家好&#xff0c;我是小彭。 今天分享到一种非常有趣的数据结构 —— 前缀和数组。前缀和…

每日一题|2022-11-8|1684. 统计一致字符串的数目|哈希表|Golang

1684. 统计一致字符串的数目 思路1:丢人做法 哈希记录allowed&#xff0c;暴力遍历words所有字母&#xff0c;如果有不在哈希表里的&#xff0c;计数。最后用words的长度减去 计数 就行。 func countConsistentStrings(allowed string, words []string) int {has1 : make(map[…