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

C语言初阶习题【19】三子棋游戏

1.实现三子棋游戏

2.思路

我们把游戏实现部分放在game.c和game.h中,把游戏的测试代码放到test.c中
main函数在test.c中。

2.1 test.c中

  1. 先写main 函数,在main函数中调用test函数。
int main()
{test();return 0;
}
  1. test.c函数实现让玩家进行选择是否要进行游戏
    这里用到了do…while语句,先上来打印一个菜单,让玩家进行输入,根据玩家输入进入不同的分支。
void test()
{int input = 0;do{manu();printf("请输入你的选择:\n");scanf("%d", &input);switch(input){case 1:game();break;case 0:printf("您已退出游戏,欢迎下次再来!\n");break;default:printf("您的选择有误,请重新输入:\n");}} while (input);
}
  1. manu()函数很简单,直接print打印即可。和我们之前的猜数字游戏是一样的思路

void manu(void)
{printf("=====================\n");printf("=====1:开始游戏=====\n");printf("=====0:退出游戏=====\n");printf("=====================\n");
}

这里写完,可以把game()函数先屏蔽掉看看效果,输入其他数值直接报错让玩家继续输,输入1直接break,循环继续,输入0就直接退出了。

在这里插入图片描述

2.2 game()的实现

game()函数实现这部分是游戏流程。game()也是放在test.c中。但是涉及到game函数具体实现都会放到game.c中去。
我们先表示棋盘:创建一个 3*3的二维数组,每个元素是一个char类型,'X’表示玩家1、'O’表示玩家2、'空格’表示空白。 我在game.c函数实现中设计了如果是和局的话用‘h’表示
因为只要游戏没有结束,就要一直下棋,所以要用到循环while

  • 游戏流程:
    (1)创建棋盘,并初始化~把所有位置都设为空格
    (2)打印棋盘
    while(1)
    {
    (3)玩家进行落子,让玩家来输入一组坐标(row,col),进行落子
    (4)进行判定,有任何一方获胜或者平局就break;
    (5)电脑进行落子~ 电脑随机落子
    (6)进行判定,有任何一方获胜或者平局就break;
    }
    (7)判定是哪一方获胜或者平局了
  • 代码实现
void game()
{//0.创建棋盘char chessBoard[ROW_MAX][COL_MAX] = { 0 };//1.初始化棋盘init(chessBoard, ROW_MAX, COL_MAX);//2.打印棋盘print(chessBoard, ROW_MAX, COL_MAX);char ret = ' ';//这个需要定义在while之外while (1){//3.玩家下棋palyer(chessBoard, ROW_MAX, COL_MAX);print(chessBoard, ROW_MAX, COL_MAX);ret = is_Win(chessBoard, ROW_MAX, COL_MAX);if ( ret!= ' '){break;}//4.电脑下棋computer(chessBoard, ROW_MAX, COL_MAX);print(chessBoard, ROW_MAX, COL_MAX);ret = is_Win(chessBoard, ROW_MAX, COL_MAX);if (ret != ' '){break;}}if (ret == 'X'){printf("玩家获胜\n");}else if (ret== 'O'){printf("电脑获胜\n");}else if(ret== 'h'){printf("平局\n");}}

2.3 game.c函数实现

我们注意game.c和game.h是配套使用的,game.c中的函数需要在game.h中进行声明。
在这里插入图片描述
在.c文件中需要引入我们自己写的.h头文件,用的是“ ”,一般引用库函数用的< >

#include "game.h"

2.3.1 棋盘初始化

init(chessBoard, ROW_MAX, COL_MAX);
最简单的写法就是使用for循环直接遍历,给每个元素初始化为空格,后面有学到了用memset函数,直接初始化。

memset函数的头文件是<string.h> 。这个的使用可以自己搜下,比较简单有三个参数,第一个是要初始化的元素地址,我们这里就是数组首元素,第二个参数是要初始化的值,我们这里是空格,第三个就是要初始化的长度,

//棋盘初始化
void init(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col)
{
#if 0for (int row = 0; row < MAX_ROW; row++){for (int col = 0; col < MAX_COL; col++){chessBoard[row][col] = ' ';}}
#endifmemset(chessBoard, ' ', ROW_MAX * COL_MAX * sizeof(char));
}

2.3.2 棋盘打印

void print(char chessBoard[ROW_MAX][COL_MAX], int row, int col)
思路:这个地方要考虑到打印我们的棋盘,否则全是空格就看不到任何输出。

void print(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col){for (int row = 0; row < ROW_MAX; row++){printf("+---+---+---+\n");printf("| %c | %c | %c |\n", chessBoard[row][0], chessBoard[row][1], chessBoard[row][2]);}printf("+---+---+---+\n");
}

2.3.2 玩家下棋

  • void palyer(char chessBoard[ROW_MAX][COL_MAX], int row, int col)
  • 思路:只要位置不为空就可以下棋,要注意限制玩家输入范围。
  • 代码实现
//玩家下棋
void palyer(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col)
{printf("玩家下棋:\n");int x = 0;int y = 0;while (1){printf("请输入要下棋的坐标:x y\n");scanf("%d %d", &x, &y);if (x<0 || x>=ROW_MAX || y<0 || y>=COL_MAX){printf("您的输入坐标有误请重新输入:\n");continue;}if (chessBoard[x][y] != ' '){printf("您下的位置已经有棋子了。请重新输入:\n");continue;}else{chessBoard[x][y] = 'X';break;}}
}

2.3.3 电脑下棋

  • void computer(char chessBoard[ROW_MAX][COL_MAX], int row, int col)
  • 思路:电脑需要使用rand()函数生成随机数进行下棋,注意两个点,其一要限制输入0 1 2不能超过3,其二需要配合srand()函数一起使用,srand()需要用到时间戳time()函数,我们这个只需要调用一次放在了test函数中。这个在猜数字游戏里面也有实现过。rand函数的头文件是<stdlib.h> time函数的头文件是<time.h>
  • 代码实现
void test()
{int input = 0;srand((unsigned int)time(NULL)); //在循环外面do{manu();printf("请输入你的选择:\n");scanf("%d", &input);switch(input){case 1://game();break;case 0:printf("您已退出游戏,欢迎下次再来!\n");break;default:printf("您的选择有误,请重新输入:\n");}} while (input);
}

//电脑下棋
void computer(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col)
{printf("电脑下棋:\n");while (1){int a = rand() % ROW_MAX;int b = rand() % COL_MAX;if (chessBoard[a][b] != ' '){continue;}chessBoard[a][b] = 'O';break;}}

2.3.4 判断输赢

  • char is_Win(char chessBoard[ROW_MAX][COL_MAX], int row, int col)

  • 思路:这里之所以是char类型的返回值,是为了能够方便我们进行判断是谁赢了。判断的思路很简单,判断三行是否一致,三列是否一致,对角线是否一致,棋盘是否下满为和局,这里涉及到一个棋盘是否满的函数,这个函数我们只需要我们的game.c中使用,所以给添加了static,关闭它的外部属性,其他.c文件都不能调用我们这个函数。

  • 代码实现

static int is_Full(char chessBoard[ROW_MAX][COL_MAX])
{int i = 0;int j = 0;for (i = 0; i < ROW_MAX; i++){for (j = 0; j < COL_MAX; j++){if (chessBoard[i][j] == ' '){return 0;}}}return 1;
}char is_Win(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col)
{//判断三行int i = 0;for (i = 0; i < row; i++){if (chessBoard[i][0] ==chessBoard[i][1] && chessBoard[i][1] == chessBoard[i][2]&& chessBoard[i][0] != ' '){return chessBoard[i][0];}}//判断三列for (i = 0; i < col; i++){if (chessBoard[0][i] == chessBoard[1][i] && chessBoard[1][i] == chessBoard[2][i]&& chessBoard[0][i] != ' '){return chessBoard[0][i];}}//判断对角线if (chessBoard[0][0] == chessBoard[1][1] && chessBoard[1][1] == chessBoard[2][2]&& chessBoard[0][0] != ' '){return chessBoard[0][0];}if (chessBoard[2][0] == chessBoard[2][2] && chessBoard[2][2] == chessBoard[0][2]&& chessBoard[0][2] != ' '){return chessBoard[0][2];}if (is_Full(chessBoard)){return 'h';//和局}return ' ';//游戏继续}

我在写这部分的时候各种出错,有时候是少了一个等号,有时候是用错了循环变量,调试真的很重要,当发现自己的错误的时候有时候真的哭笑不得,还好有调试功能,可以让我一步一步跟着代码走排查自己的问题。

3.代码实现

  • test.c

#include "game.h"void manu(void)
{printf("=====================\n");printf("=====1:开始游戏=====\n");printf("=====0:退出游戏=====\n");printf("=====================\n");
}void game()
{//0.创建棋盘char chessBoard[ROW_MAX][COL_MAX] = { 0 };//1.初始化棋盘init(chessBoard, ROW_MAX, COL_MAX);//2.打印棋盘print(chessBoard, ROW_MAX, COL_MAX);char ret = ' ';while (1){//3.玩家下棋palyer(chessBoard, ROW_MAX, COL_MAX);print(chessBoard, ROW_MAX, COL_MAX);ret = is_Win(chessBoard, ROW_MAX, COL_MAX);if ( ret!= ' '){break;}//4.电脑下棋computer(chessBoard, ROW_MAX, COL_MAX);print(chessBoard, ROW_MAX, COL_MAX);ret = is_Win(chessBoard, ROW_MAX, COL_MAX);if (ret != ' '){break;}}if (ret == 'X'){printf("玩家获胜\n");}else if (ret== 'O'){printf("电脑获胜\n");}else if(ret== 'h'){printf("平局\n");}}void test()
{int input = 0;srand((unsigned int)time(NULL));do{manu();printf("请输入你的选择:\n");scanf("%d", &input);switch(input){case 1:game();break;case 0:printf("您已退出游戏,欢迎下次再来!\n");break;default:printf("您的选择有误,请重新输入:\n");}} while (input);
}int main()
{test();}
  • game.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>#define ROW_MAX 3
#define COL_MAX 3//棋盘初始化
void init(char chessBoard[ROW_MAX][COL_MAX],int  row,int  col );//棋盘打印
void print(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col);//玩家下棋
void palyer(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col);//电脑下棋
void computer(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col);//判断输赢
char is_Win(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col);
  • game.c
#include "game.h"//棋盘初始化
void init(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col)
{memset(chessBoard, ' ', ROW_MAX * COL_MAX * sizeof(char));
}//棋盘打印
void print(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col){for (int row = 0; row < ROW_MAX; row++){printf("+---+---+---+\n");printf("| %c | %c | %c |\n", chessBoard[row][0], chessBoard[row][1], chessBoard[row][2]);}printf("+---+---+---+\n");
}//玩家下棋
void palyer(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col)
{printf("玩家下棋:\n");int x = 0;int y = 0;while (1){printf("请输入要下棋的坐标:x y\n");scanf("%d %d", &x, &y);if (x<0 || x>=ROW_MAX || y<0 || y>=COL_MAX){printf("您的输入坐标有误请重新输入:\n");continue;}if (chessBoard[x][y] != ' '){printf("您下的位置已经有棋子了。请重新输入:\n");continue;}else{chessBoard[x][y] = 'X';break;}}
}//电脑下棋
void computer(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col)
{printf("电脑下棋:\n");while (1){int a = rand() % ROW_MAX;int b = rand() % COL_MAX;if (chessBoard[a][b] != ' '){continue;}chessBoard[a][b] = 'O';break;}}static int is_Full(char chessBoard[ROW_MAX][COL_MAX])
{int i = 0;int j = 0;for (i = 0; i < ROW_MAX; i++){for (j = 0; j < COL_MAX; j++){if (chessBoard[i][j] == ' '){return 0;}}}return 1;
}//判断输赢
//返回X表示玩家获胜
//返回O表示电脑获胜
//返回h表示和局
//返回j表示游戏继续char is_Win(char chessBoard[ROW_MAX][COL_MAX], int  row, int  col)
{//判断三行int i = 0;for (i = 0; i < row; i++){if (chessBoard[i][0] ==chessBoard[i][1] && chessBoard[i][1] == chessBoard[i][2]&& chessBoard[i][0] != ' '){return chessBoard[i][0];}}//判断三列for (i = 0; i < col; i++){if (chessBoard[0][i] == chessBoard[1][i] && chessBoard[1][i] == chessBoard[2][i]&& chessBoard[0][i] != ' '){return chessBoard[0][i];}}//判断对角线if (chessBoard[0][0] == chessBoard[1][1] && chessBoard[1][1] == chessBoard[2][2]&& chessBoard[0][0] != ' '){return chessBoard[0][0];}if (chessBoard[2][0] == chessBoard[2][2] && chessBoard[2][2] == chessBoard[0][2]&& chessBoard[0][2] != ' '){return chessBoard[0][2];}if (is_Full(chessBoard)){return 'h';//和局}return ' ';//游戏继续}

相关文章:

C语言初阶习题【19】三子棋游戏

1.实现三子棋游戏 2.思路 我们把游戏实现部分放在game.c和game.h中&#xff0c;把游戏的测试代码放到test.c中 main函数在test.c中。 2.1 test.c中 先写main 函数&#xff0c;在main函数中调用test函数。 int main() {test();return 0; }test.c函数实现让玩家进行选择是否…...

Linux day 1129

家人们今天继续学习Linux&#xff0c;ok话不多说一起去看看吧 三.Linux常用命令 3.1 Linux命令体验 3.1.1 常用命令演示 在这一部分中&#xff0c;我们主要介绍几个常用的命令&#xff0c;让大家快速感 受以下 Linux 指令的操作方式。主要包含以下几个指令&#xff1a; ls命…...

【优化算法】梯度优化算法:一种新的原启发式优化算法算法

目录 1.摘要2.算法原理3.结果展示4.参考文献5.获取代码 1.摘要 本文提出了一种新型的元启发式优化算法——梯度优化器&#xff08;Gradient-based Optimizer, GBO&#xff09;。GBO算法灵感来源于牛顿法&#xff0c;采用两个主要操作&#xff1a;梯度搜索规则&#xff08;Grad…...

内部类(3)

大家好&#xff0c;今天我们继续来看看内部类&#xff0c;今天我们来学习一下内部类的分类&#xff0c;我们来看看一共有几种&#xff0c;它们有什么作用&#xff0c;那么话不多说&#xff0c;我们直接开始。 9.1 内部类的分类 先来看下,内部类都可以在一个类的哪些位置进行定…...

svn分支相关操作(小乌龟操作版)

在开发工作中进行分支开发&#xff0c;涉及新建分支&#xff0c;分支切换&#xff0c;合并分支等 新建远程分支 右键选择branch/tagert按钮 命名分支的路径名称 点击确定后远程分支就会生成一个当时命名的文件夹&#xff08;开发分支&#xff09; 分支切换 一般在开发阶段&a…...

rust_shyper

title: 探索 Rust_Shyper&#xff1a;系统编程的新前沿 date: ‘2024-12-30’ category: blog tags: Rust_ShyperRust 语言系统编程性能与安全 sig: Virt archives: ‘2024-12’ author:way_back summary: Rust_Shyper 作为基于 Rust 语言的创新项目&#xff0c;在系统编程领域…...

HAL 库 HAL_UARTEx_ReceiveToIdle_IT 函数解析

一、存在位置&#xff1a;stm32f1xx_hal_uart.c 二、具体代码 二、返回值&#xff1a;HAL_StatusTypeDef 通过查看返回值HAL_StatusTypeDef在stm32f1xx_hal_edf.h文件中定义为结构体类型。 status&#xff1a;&#xff08;进展的&#xff09;状况&#xff0c;情形 三、函数名…...

【ArcGIS Pro】完整的nc文件整理表格模型构建流程及工具练习数据分享

学术科研啥的要用到很多数据&#xff0c;nc文件融合了时间空间数据是科研重要文件。之前分享过怎样将nc文件处理成栅格后整理成表格。小编的读者还是有跑不通整个流程的&#xff0c;再来做一篇总结篇&#xff0c;也分享下练习数据跟工具&#xff0c;如果还是弄不了的&#xff0…...

REDIS的集群

REDIS的集群模式&#xff1a; 主从模式&#xff1a;redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上 特点&#xff1a; 主从模式和数据库的主从模式&#xff08;工作模式&#xff09;是一样的&#xff0c;主负责写入&#xff0c;然后把写入到数据同步到从&…...

酒店管理系统的设计与实现【源码+文档+部署讲解】

酒店管理系统的设计与实现 摘 要 中国经济近几年来取得蓬勃飞速发展&#xff0c;使得人民生活水平的要求和生活的质量有了很高的要求。因此人们对外出旅游和就餐的需求也越来越大。同时&#xff0c;随着我国科技水平的兴起和对互联网新时代的大力支持&#xff0c;酒店管理系统在…...

[论文阅读] (34)ESWA2024 基于SGDC的轻量级入侵检测系统

《娜璋带你读论文》系列主要是督促自己阅读优秀论文及听取学术讲座&#xff0c;并分享给大家&#xff0c;希望您喜欢。由于作者的英文水平和学术能力不高&#xff0c;需要不断提升&#xff0c;所以还请大家批评指正&#xff0c;非常欢迎大家给我留言评论&#xff0c;学术路上期…...

从社区共识到资本效能:解析SYNBO的去中心化投资协议创新

Web3 资本市场正处于深刻变革的关键节点。随着去中心化技术的不断进化&#xff0c;传统风险投资模式逐渐显现出效率、透明性与公平性等方面的局限性。而 SYNBO 的出现&#xff0c;为这一市场注入了全新的可能性。 作为新一代去中心化风险投资协议&#xff0c;SYNBO 不仅创新性地…...

一、数据库 Sqlite3 资料

SQLite3 教程 SQLite3 是一个轻量级的嵌入式数据库引擎&#xff0c;它不需要单独的服务器进程&#xff0c;数据库直接存储在磁盘文件中。Python 内置了 sqlite3 模块&#xff0c;可以方便地操作 SQLite 数据库。以下是 SQLite3 的详细教程。 1. SQLite3 简介 SQLite3 是一个自…...

Passlib库介绍及使用指南

什么是Passlib&#xff1f; Passlib是一个强大的Python密码哈希库&#xff0c;它支持多种哈希算法和工具。 Passlib不仅提供了易于使用的API&#xff0c;还集成了多种安全特性&#xff0c;如加盐、密钥派生函数等&#xff0c;广泛应用于用户账户系统、敏感数据保护和多因素认证…...

模型选择+过拟合欠拟合

训练误差和泛化误差 训练误差&#xff1a;模型在训练数据上的误差 泛化误差&#xff1a;模型在新数据上的误差 验证数据集&#xff1a;一个用来评估模型好坏的数据集 例如拿出50%的数据作为训练 测试数据集&#xff1a;只能用一次 K则交叉验证 在没有足够数据时使用 算法…...

绝美的数据处理图-三坐标轴-散点图-堆叠图-数据可视化图

clc clear close all %% 读取数据 load(MyColor.mat) %读取颜色包for iloop 1:25 %提取工作表数据data0(iloop) {readtable(data.xlsx,sheet,iloop)}; end%% 解析数据 countzeros(23,14); for iloop 1:25index(iloop) { cell2mat(table2array(data0{1,iloop}(1,1)))};data(i…...

损失函数-二分类和多分类

二分类和多分类的损失函数 二分类 损失函数 L ( y , y ^ ) − ( y l o g ( y ^ ) ) ( 1 − y ) l o g ( 1 − y ^ ) L(y,\hat{y}) -(ylog(\hat{y})) (1-y)log(1-\hat{y}) L(y,y^​)−(ylog(y^​))(1−y)log(1−y^​) 其中真实标签表示为y&#xff08;取值为 0 或 1&#…...

汽车损坏识别检测数据集,使用yolo,pasical voc xml,coco json格式标注,6696张图片,可识别11种损坏类型,识别率89.7%

汽车损坏识别检测数据集&#xff0c;使用yolo&#xff0c;pasical voc xml&#xff0c;coco json格式标注&#xff0c;6696张图片&#xff0c;可识别11种损坏类型损坏&#xff1a; 前挡风玻璃&#xff08;damage-front-windscreen &#xff09; 损坏的门 &#xff08;damaged-d…...

从 Elastic 迁移到 Easysearch 指引

从 Elasticsearch 迁移到 Easysearch 需要考虑多个方面&#xff0c;这取决于当前使用的 Elasticsearch 版本、能容忍的停机时间、应用需求等。在此背景下&#xff0c;我们梳理了一下通用的升级指引&#xff0c;方便大家进行迁移工作。 迁移路径 Elasticsearch 版本快照兼容推…...

Yapi RCE 复现和批量编写

一、漏洞复现 首先祭出fofa&#xff0c;搜索语句为 app"yapi"&#xff0c;但是为了避开国内&#xff0c;所以使用 app"yapi" && country"SG"&#xff0c;SG为新加坡&#xff0c;结果如图 虽然有30页&#xff0c;但是能利用的可能也没几…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...