win32下 多线程(多一个线程)GDI 坦克大战

2023-05-16

一个字。累并快乐,兴趣索然。。。。追回梦想

学习WINDOWS编程2个月。下一步:DIrectX9...

自己加载资源:素材在下面自行下载(修改成BMP格式)

resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Tanker.rc 使用
//
#define IDB_ENEMY                       101
#define IDB_HERO                        103
#define IDI_ICON                        105
#define IDB_ARMS                        107
#define IDB_BOOMENM                     108
#define IDB_HEROBOOM                    109

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        110
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

 

 

main.cpp:

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "resource.h"
#include <math.h>
#include <process.h>
#pragma comment (lib,"msimg32.lib") //处理BMP背景色函数

//常量。
#define MAX_STR 32
#define HERO_SPEED 3
#define ARM_NUM 50
#define ARM_SPEED 5
#define  ENM_NUM  8
#define ENM_SPEED 1
#define ENM_CHANGDIR 4  //enemy changdir probability 。

//全局变量。
TCHAR wndclassname[MAX_STR] = TEXT("TankerWar");
TCHAR wndtitlename[MAX_STR] = TEXT("小坦克大战");
HINSTANCE hInst;
HWND hwnd;
HDC hdc, memdc, bufdc;
RECT wndrect;
HBITMAP hHeroBMP, hEnemyBMP, hNullBMP, hArmBMP, hEnemyboomBMP, hHeroBoombmp;

//游戏各类SPRITE参数。
enum MOVEDIR { left, up, down, right };
enum ISDIE { die, nodie };
enum ARMTYPE { heroarm, enemyarm };
struct TKPOINT
{
	INT x; INT y;
};
struct HERO
{
	ISDIE isdie;
	MOVEDIR movedir;
	TKPOINT pstn;

};
struct ENEMY
{
	ISDIE isdie;
	MOVEDIR movedir;
	TKPOINT pstn;
};
struct ARMS
{
	ISDIE isdie;
	MOVEDIR movedir;
	TKPOINT pstn;
	ARMTYPE armtp;
};

//创建对象。(可惜了还不会用抽象成对象)
ARMS arms[ARM_NUM];
HERO hero;
ENEMY enemy[ENM_NUM];

//函数声明
LRESULT WINAPI WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); //消息主函数
void GameInit();  //游戏初始化
void DispalyScreen();  //显示SPRITE
void Fire(ENEMY &enemy, ARMTYPE armstype);//敌人开火
void HeroFire(ARMTYPE);//主角开火
void EnemyAutoMove(LPVOID param);

void DispalyScreen() {
	hdc = GetDC(hwnd);
	memdc = CreateCompatibleDC(hdc);
	bufdc = CreateCompatibleDC(hdc);
	hNullBMP = CreateCompatibleBitmap(hdc, wndrect.right, wndrect.bottom);
	SelectObject(memdc, hNullBMP); //设定CreateCompatibleBitmap的大小,否则不会显示在HDC上。
	//Display arms(没有死亡的子弹)
	hArmBMP = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_ARMS));
	SelectObject(bufdc, hArmBMP);
	for (int i = 0; i < ARM_NUM; i++)
	{
		if (arms[i].isdie == nodie)
		{
			TransparentBlt(memdc, arms[i].pstn.x, arms[i].pstn.y, 7, 7, bufdc, 0, 0, 7, 7, RGB(255, 255, 255));
			switch (arms[i].movedir)
			{
			case left:
				arms[i].pstn.x > 0 ?
					arms[i].pstn.x -= ARM_SPEED : arms[i].isdie = die;
				break;
			case up:
				arms[i].pstn.y > 0 ?
					arms[i].pstn.y -= ARM_SPEED : arms[i].isdie = die;
				break;
			case right:
				arms[i].pstn.x < wndrect.right ?
					arms[i].pstn.x += ARM_SPEED : arms[i].isdie = die;
				break;
			case down:
				arms[i].pstn.y < wndrect.bottom ?
					arms[i].pstn.y += ARM_SPEED : arms[i].isdie = die;
				break;
			}
		}
	}
	//enemy display and move 
	hEnemyBMP = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_ENEMY));
	SelectObject(bufdc, hEnemyBMP);
	for (int j = 0; j < ENM_NUM; j++)
	{
		if (enemy[j].isdie == nodie)
		{
			switch (enemy[j].movedir)
			{
			case left:
				enemy[j].pstn.x > 0 ?
					enemy[j].pstn.x -= ENM_SPEED : enemy[j].pstn.x = 0;
				TransparentBlt(memdc, enemy[j].pstn.x, enemy[j].pstn.y, 33, 33, bufdc, 0, 0, 33, 33, RGB(0, 0, 0));

				break;
			case up:
				enemy[j].pstn.y > 0 ?
					enemy[j].pstn.y -= ENM_SPEED : enemy[j].pstn.y = 0;
				TransparentBlt(memdc, enemy[j].pstn.x, enemy[j].pstn.y, 33, 33, bufdc, 33, 0, 33, 33, RGB(0, 0, 0));
				break;
			case right:
				enemy[j].pstn.x < wndrect.right - 33 ?
					enemy[j].pstn.x += ENM_SPEED : enemy[j].pstn.x = wndrect.right - 33;
				TransparentBlt(memdc, enemy[j].pstn.x, enemy[j].pstn.y, 33, 33, bufdc, 66, 0, 33, 33, RGB(0, 0, 0));
				break;
			case down:
				enemy[j].pstn.y < wndrect.bottom - 33 ?
					enemy[j].pstn.y += ENM_SPEED : enemy[j].pstn.y = wndrect.bottom - 33;
				TransparentBlt(memdc, enemy[j].pstn.x, enemy[j].pstn.y, 33, 33, bufdc, 99, 0, 33, 33, RGB(0, 0, 0));
				break;
			}
		}
	}
	// display hero(这里可以将主角调整成自动移动)
	hHeroBMP = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_HERO));
	SelectObject(bufdc, hHeroBMP);
	if (hero.isdie == nodie)
	{
		switch (hero.movedir)
		{
		case left:
			TransparentBlt(memdc, hero.pstn.x, hero.pstn.y, 33, 33, bufdc, 0, 0, 33, 33, RGB(0, 0, 0));
			break;
		case up:
			TransparentBlt(memdc, hero.pstn.x, hero.pstn.y, 33, 33, bufdc, 33, 0, 33, 33, RGB(0, 0, 0));
			break;
		case right:
			TransparentBlt(memdc, hero.pstn.x, hero.pstn.y, 33, 33, bufdc, 66, 0, 33, 33, RGB(0, 0, 0));
			break;
		case down:
			TransparentBlt(memdc, hero.pstn.x, hero.pstn.y, 33, 33, bufdc, 99, 0, 33, 33, RGB(0, 0, 0));
			break;
		}
	}
	//碰撞检测
	hEnemyboomBMP = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BOOMENM));
	hHeroBoombmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_HEROBOOM));
	for (int i = 0; i < ARM_NUM; i++)
	{
		if (arms[i].isdie == nodie)
		{	//检测敌人中弹
			for (int j = 0; j < ENM_NUM; j++)
			{
				if (arms[i].armtp == heroarm && enemy[j].isdie == nodie && abs(enemy[j].pstn.x + 13 - arms[i].pstn.x) < 18 && abs(enemy[j].pstn.y + 13 - arms[i].pstn.y) < 18)
				{   
					SelectObject(bufdc, hEnemyboomBMP);
					TransparentBlt(memdc, enemy[j].pstn.x - 3, enemy[j].pstn.y - 3, 40, 40, bufdc, 120, 0, 40, 40, RGB(0, 0, 0));
					BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
					TransparentBlt(memdc, enemy[j].pstn.x - 3, enemy[j].pstn.y - 3, 40, 40, bufdc, 80, 0, 40, 40, RGB(0, 0, 0));
					BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
					TransparentBlt(memdc, enemy[j].pstn.x - 3, enemy[j].pstn.y - 3, 40, 40, bufdc, 40, 0, 40, 40, RGB(0, 0, 0));
					BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
					TransparentBlt(memdc, enemy[j].pstn.x - 3, enemy[j].pstn.y - 3, 40, 40, bufdc, 0, 0, 40, 40, RGB(0, 0, 0));
					BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
					arms[i] = { };
					enemy[j] = {  };
				}
			}
			//检测主角中弹
			if (arms[i].armtp == enemyarm && hero.isdie == nodie
				&& abs(hero.pstn.x + 13 - arms[i].pstn.x) < 18 && abs(hero.pstn.y + 13 - arms[i].pstn.y) < 18)
			{
				SelectObject(bufdc, hHeroBoombmp);
				TransparentBlt(memdc, hero.pstn.x - 8, hero.pstn.y - 8, 50, 50, bufdc, 300, 0, 50, 50, RGB(0, 0, 0));
				BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
				TransparentBlt(memdc, hero.pstn.x - 8, hero.pstn.y - 8, 50, 50, bufdc, 250, 0, 50, 50, RGB(0, 0, 0));
				BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
				TransparentBlt(memdc, hero.pstn.x - 8, hero.pstn.y - 8, 50, 50, bufdc, 200, 0, 50, 50, RGB(0, 0, 0));
				BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
				TransparentBlt(memdc, hero.pstn.x - 8, hero.pstn.y - 8, 50, 50, bufdc, 150, 0, 50, 50, RGB(0, 0, 0));
				BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
				TransparentBlt(memdc, hero.pstn.x - 8, hero.pstn.y - 8, 50, 50, bufdc, 100, 0, 50, 50, RGB(0, 0, 0));
				BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
				TransparentBlt(memdc, hero.pstn.x - 8, hero.pstn.y - 8, 50, 50, bufdc, 50, 0, 50, 50, RGB(0, 0, 0));
				BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
				TransparentBlt(memdc, hero.pstn.x - 8, hero.pstn.y - 8, 50, 50, bufdc, 0, 0, 50, 50, RGB(0, 0, 0));
				BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
				hero.isdie = die;

				MessageBox(NULL, TEXT("you falt"), TEXT("loser"), MB_OK);
			}
		}
	}
	BitBlt(hdc, 0, 0, wndrect.right, wndrect.bottom, memdc, 0, 0, SRCCOPY);
	DeleteObject(hHeroBoombmp);
	DeleteObject(hEnemyboomBMP);
	DeleteObject(hEnemyBMP);
	DeleteObject(hHeroBMP);
	DeleteObject(hNullBMP);
	DeleteObject(hArmBMP);
	DeleteDC(bufdc);
	DeleteDC(memdc);
	ReleaseDC(hwnd, hdc);
}

void GameInit() {
	//hero init
	hero.isdie = nodie;
	hero.pstn.x = (int)wndrect.right / 2 - 17;
	hero.pstn.y = (int)wndrect.bottom - 33;
	hero.movedir = up;

	for (int i = 0; i < ENM_NUM; i++)
	{
		srand((UINT)GetTickCount()*i);
		int trand = rand();
		if (enemy[i].isdie != nodie)
		{
			enemy[i].isdie = nodie;
			enemy[i].movedir = (MOVEDIR)(trand % 4);
			enemy[i].pstn = { trand % (wndrect.right - 33),trand % (wndrect.bottom - 33) };
		}
	}
}
void Fire(ENEMY &enemy, ARMTYPE armstype) {
	for (int i = 0; i < ARM_NUM; i++)
	{
		if (arms[i].isdie != nodie)
		{
			arms[i].isdie = nodie;
			arms[i].movedir = enemy.movedir;
			arms[i].armtp = armstype;
			if (arms[i].armtp == enemyarm)
			{
				switch (enemy.movedir)
				{
				case left:
					arms[i].pstn.x = enemy.pstn.x + 3;
					arms[i].pstn.y = enemy.pstn.y + 13;
					break;
				case up:
					arms[i].pstn.x = enemy.pstn.x + 13;
					arms[i].pstn.y = enemy.pstn.y + 3;
					break;
				case right:
					arms[i].pstn.x = enemy.pstn.x + 29;
					arms[i].pstn.y = enemy.pstn.y + 13;
					break;
				case down:
					arms[i].pstn.x = enemy.pstn.x + 13;
					arms[i].pstn.y = enemy.pstn.y + 29;
					break;
				}
				break;

			}
		}
	}
}
void HeroFire(ARMTYPE armstype) {
	for (int i = 0; i < ARM_NUM; i++)
	{
		if (hero.isdie == die)
		{
			break;
		}
		if (arms[i].isdie != nodie)
		{
			arms[i].isdie = nodie;
			arms[i].movedir = hero.movedir;
			//arms[i].pstn.x = hero.pstn.x;
			arms[i].armtp = armstype;
			if (arms[i].armtp == heroarm)
			{
				switch (hero.movedir)
				{
				case left:
					arms[i].pstn.x = hero.pstn.x + 3;
					arms[i].pstn.y = hero.pstn.y + 13;
					break;
				case up:
					arms[i].pstn.x = hero.pstn.x + 13;
					arms[i].pstn.y = hero.pstn.y + 3;
					break;
				case right:
					arms[i].pstn.x = hero.pstn.x + 29;
					arms[i].pstn.y = hero.pstn.y + 13;
					break;
				case down:
					arms[i].pstn.x = hero.pstn.x + 13;
					arms[i].pstn.y = hero.pstn.y + 29;
					break;
				}
			}
			break;
		}
	}
}
void EnemyAutoMove(LPVOID param) {
	while (TRUE)
	{
		Sleep(800);//否则CPU会飙
		srand(UINT(GetTickCount() * 1101));
		MOVEDIR dir;
		dir = (MOVEDIR)(rand() % 4);
		for (int p = 0; p < ENM_NUM; p++)
		{
			if (enemy[p].pstn.x<ENM_SPEED || enemy[p].pstn.y<ENM_SPEED ||
				enemy[p].pstn.x>wndrect.right - 40 || enemy[p].pstn.y>wndrect.bottom - 40)
			{
				enemy[p].movedir = dir;
			}
		}
		if (enemy[rand() % ENM_NUM].isdie == nodie)
			enemy[rand() % ENM_NUM].movedir = dir;
		int f = rand() % ENM_NUM;
		if (enemy[f].isdie == nodie)
			Fire(enemy[f], enemyarm);
	}
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prehInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASS wcs = { CS_HREDRAW | CS_VREDRAW,WndProc,0,0,hInstance,LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON)),LoadCursor(NULL,IDC_UPARROW),HBRUSH(BLACK_BRUSH),NULL,wndclassname };
	hInst = hInstance;
	if (!RegisterClass(&wcs))
	{
		return 0;
	}
	hwnd = CreateWindow(wndclassname, wndtitlename, WS_OVERLAPPEDWINDOW&~WS_THICKFRAME, CW_USEDEFAULT, 0, 500, 500, NULL, NULL, hInstance, NULL);
	if (hwnd == NULL)
	{
		return 0;
	}
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	GameInit(); //角色类初始化
	MSG msg = { 0 };
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			Sleep(30);//否则CPU会飙
			DispalyScreen();
		}
	}
	UnregisterClass(wndclassname, hInstance);
	return 0;
}
LRESULT WINAPI WndProc(HWND hwnd, UINT mesage, WPARAM wparam, LPARAM lparam) {
	switch (mesage)
	{
	case WM_LBUTTONUP:
		HeroFire(heroarm);
		break;
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC whdc = BeginPaint(hwnd, &ps);
		GetClientRect(hwnd, &wndrect);
		EndPaint(hwnd, &ps);
		break;
	}
	case WM_CREATE:
	{
		_beginthread(EnemyAutoMove, 0, NULL);//创建线程(敌人自动随机变向和开火)
		break;
	}
	case WM_RBUTTONDOWN:
		GameInit();
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_KEYDOWN:
		if (hero.isdie == die)
		{
			break;
		}
		switch (wparam)
		{
		case VK_UP:
			if (hero.pstn.y > 0)
			{
				hero.pstn.y -= HERO_SPEED;
				hero.movedir = up;
			}
			else
			{
				hero.pstn.y = 0;
			}
			break;
		case VK_DOWN:
			if (hero.pstn.y < wndrect.bottom - 33)
			{
				hero.pstn.y += HERO_SPEED;
				hero.movedir = down;
			}
			else
			{
				hero.pstn.y = wndrect.bottom - 33;
			}
			break;
		case VK_LEFT:
			if (hero.pstn.x > 0)
			{
				hero.pstn.x -= HERO_SPEED;
				hero.movedir = left;
			}
			else
			{
				hero.pstn.x = 0;
			}
			break;
		case VK_RIGHT:
			if (hero.pstn.x < wndrect.right - 33)
			{
				hero.pstn.x += HERO_SPEED;
				hero.movedir = right;
			}
			else
			{
				hero.pstn.x = wndrect.right - 33;
			}
			break;
		}
	default:
		return DefWindowProc(hwnd, mesage, wparam, lparam);
		break;
	}
	return 0;
}

 

 

终于搞定。

 

 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

win32下 多线程(多一个线程)GDI 坦克大战 的相关文章

  • R语言 PCA(主成分分析)

    R语言 PCA 转自 xff1a http www cnblogs com longzhongren p 4300593 html 1 关键点 综述 xff1a 主成分分析 因子分析 典型相关分析 xff0c 三种方法的共同点主要是用来对数
  • 使用Pandas对数据进行筛选和排序

    使用Pandas对数据进行筛选和排序 转自 xff1a http bluewhale cc 2016 08 06 use pandas filter and sort html 筛选和排序是Excel中使用频率最多的功能 xff0c 通过这
  • linux 下安装blat软件

    linux 下安装blat软件 blat是一款很经典的比对工具 xff0c 与blast相比 xff0c 具有速度快 共线性输出比对结果等优点 但是 xff0c blat源码包里面的README文件写得很不清楚 xff0c 这里 xff0c
  • 基于统计的压缩算法:游程编码

    原网址 xff1a http www cnblogs com xudong bupt p 3761417 html 基于统计的压缩算法 xff1a 游程编码 1 游程编码概念 游程编码又称 运行长度编码 或 行程编码 xff0c 是一种统计
  • BWT (Burrows–Wheeler_transform)数据转换算法

    原网址 xff1a https blog csdn net luanzheng 365 article details 78575429 BWT Burrows Wheeler transform 数据转换算法 1 什么是BWT 压缩技术主
  • pip使用豆瓣的镜像源

    抄自 xff1a https www cnblogs com ZhangRuoXu p 6370107 html pip使用豆瓣的镜像源 豆瓣镜像地址 xff1a https pypi douban com simple 虽然用easy i
  • PyVCF

    抄自 xff1a https www cnblogs com nkwy2012 p 9204088 html vcf文件的全称是variant call file xff0c 即突变识别文件 xff0c 它是基因组工作流程中产生的一种文件
  • 【Kotlin 初学者】扩展-享受编程

    作者简介 xff1a CSDN博客专家 华为云 云享专家认证 系列专栏 xff1a Kotlin 初学者 学习交流 xff1a 三人行必有我师焉 xff1b 择其善者而从之 xff0c 其不善者而改之 目录 一 介绍 二 扩展函数 2 1
  • 【Kotlin 初学者】函数式编程

    作者简介 xff1a CSDN博客专家 华为云 云享专家认证 系列专栏 xff1a Kotlin 初学者 五星好评 xff1a 左侧点一下 网页端 xff0c 移动端 xff1a https bbs csdn net topics 6039
  • centos8.5 更新失败

    今天使用yum makecache的时候出现了Error Failed to download metadata for repo 39 base 39 Cannot download repomd xml Cannot download
  • 【Kotlin 初学者】Java和Kotlin互操作

    作者简介 xff1a CSDN博客专家 华为云 云享专家认证 系列专栏 xff1a Kotlin 初学者 五星好评 xff1a 左侧点一下 网页端 xff0c 移动端 xff1a https bbs csdn net topics 6039
  • Kotlin 基础知识汇总(知识与实践相结合)

    2个月的时间总算把 Kotlin 的基础知识写完了 xff0c 下面咱们看看具体内容 xff1a 学习 Kotlin 的必要性 Kotlin 初学者 为什么要学Kotlin Kotlin 初学者 打牢基础的重要性 运行环境 Kotlin 初
  • HashMap的产生与原理

    一 HashMap的诞生 1 1 数组 数组 xff1a 一片物理上连续的大小确定的储存空间 好处 xff1a 根据下标快速的查找和修改里面的内容 缺点 xff1a 大小确定 xff0c 无法修改 添加新的元素或者删除元素比较麻烦 数组的静
  • Android 数据存储(一)-文件存储

    目录 一 数据存储概念 二 应用程序专属文件存储 2 1 访问持久文件 2 2 将数据存储到文件 2 3 从文件中读取数据 2 4 查看文件列表 2 5 删除文件 三 缓存文件 cache目录下 3 1 创建缓存文件 3 2 删除文件 四
  • 回顾2021,展望2022 | 年终总结

    你付出多少努力 xff0c 就必有多少收获 一 回顾 2021 2021 年输出109篇文章 xff0c 收获 xff1a 博客专家认证 Android领域新星创作者认证 博客之星Top50 同时也在问答模块解决了部分小伙伴的问题 xff0
  • Android 数据存储(二)-SP VS DataStore VS MMKV

    一 SharedPreferences 不同于文件的存储方式 xff0c 如果要保存的键值集合相对较小 xff0c 则应使用SharedReferences API SharedReferences对象指向一个包含键值对的文件 xff0c
  • Jetpack DataStore 你总要了解一下吧?

    目录 一 DataStore 介绍 Preferences DataStore 和 Proto DataStore 二 Preferences DataStore 2 1 添加依赖 2 2 使用 Preferences DataStore
  • Android 数据存储(四)-Room

    目录 一 概述 1 1 描述 1 2 主要部件 二 创建 Room 2 1 添加依赖项 2 2 创建数据实体 2 2 1 设置 tableName or name 属性 2 2 2 设置主键 2 2 3 忽略字段 2 3 创建数据访问对象
  • Android 抛弃IMEI改用ANDROID_ID

    介绍 之前一直使用IMEI作为唯一标识符 xff0c 缺点就是需要权限 xff1a Android 10以前 xff0c 需要READ PHONE STATE权限 Android 10限制 xff0c 需要READ PRIVILEGED P
  • Android 单例模式必知必会

    目录 一 概念 1 1 单例类 1 2 优缺点 1 2 1 优点 1 2 2 缺点 二 创建单例模式的方法 2 1 饿汉式 2 2 懒汉式 2 2 1 懒汉式 非线程安全 2 2 2 懒汉式 线程安全 2 3 双重检验锁 2 4 静态内部类

随机推荐

  • 使用netinstall重置MIKROTIK RouterOS

    相信查看本文的读者手头应该有一台Mikrotik的路由产品 xff0c 本文中出现的RouterOS是指笔者拥有的一台家庭版路由器 非Routeros玩家可以忽略本文 下图就是笔者正在使用的一个Routeros路由器 我们在给Routero
  • BigDecimal 简单使用

    目录 为什么使用BigDecimal 解决方案 构造方法 类型转换 double 转 BigDecimal BigDecimal 转 String BigDecimal 转 double int long等 加减乘除取余 divide 舍入
  • Android Framework 启动流程必知必会

    课前预习 在了解启动流程之前先了解一下下面两个概念 1 子进程与父进程的区别 1 除了文件锁以外 其他的锁都会被继承 2 各自的进程ID和父进程ID不同 3 子进程的未决告警被清除 4 子进程的未决信号集设置为空集 2 什么是写时拷贝 co
  • ADB 操作命令及用法

    ADB 操作命令及用法 文章目录 ADB 操作命令及用法一 ADB是什么 xff1f 二 ADB有什么作用 xff1f 三 ADB命令语法单一设备 模拟器连接多个设备 模拟器连接4 1 基本命令4 1 1 查看adb的版本信息4 1 2 启
  • 研究生生涯的一些经验和感悟

    研究生生涯的一些经验和感悟 引言 写这篇博客前 xff0c 我不禁要感慨一下互联网分享所带来的好处 我这里讲的分享主要是指知识 技术和个人思想的分享 网络新闻媒体更多是传播一些资讯 xff0c 而这些资讯一般不涉及深入的技术 xff0c 深
  • PyCharm上传本地项目到GitLab - MacOS版

    登录GitLab 创建一个项目 填写项目名称 xff0c 选择显示级别 复制GitLab的这个项目地址 xff0c 后面会在PyCharm里面用到 PyCharm操作 从PyCharm打开本地项目 xff0c 然后创建本地代码仓库 xff0
  • 【Python】使用Scrapy 网络爬虫框架Demo

    安装 使用PyCharm安装 xff0c 进入到PyCharm gt Preferences gt Project Interpreter xff0c 点击加号 查询框输入 Scrapy xff0c 点击 Install Package 使
  • Docker+Selenium Grid运行UI自动化

    简介 使用Selenium Grid可以分布式运行UI自动化测试 xff0c 可以同时启动多个不同的浏览器 xff0c 也可以同时启动同一个浏览器的多个session 这里使用Docker Compose来同时启动不同浏览器的容器和Sele
  • python-生成HTMLTestRunner测试报告

    一 安装HTMLTestRunner HTMLTestRunner 是 Python 标准库的 unittest 模块的一个扩展 xff0c 它可以生成 HTML的 测试报告 首先要下 HTMLTestRunner py 文件 xff0c
  • Jenkins发送测试报告邮件

    简介 总结怎么使用Jenkins执行自动化测试后发送测试报告邮件 一 系统设置 1 在Jenkins安装Email Extension Plugin插件 xff0c 如下图 xff1a 2 设置Extended E mail Notific
  • Java读取csv文件

    简介 xff1a 总结用java通过读取csv文件方法 xff0c 为用csv文件来做数据驱动测试提供解决方案 创建csv文件 用WPS表格或excel创建文件 xff0c 填写数据 xff0c 另存为选择CSV格式进行保存 xff0c 如
  • MikroTik RouterOS上网设置

    本文是一篇关于MikroTik Routeros上网配置的示例文章 xff0c 适合有一定RouterOS路由器配置基础的同学学习 网络拓扑如下图 xff0c 家用WIFI已配置并正常上网 xff0c 接口地址如图所示 xff08 大家凑合
  • 搭建PHP开发环境(Apache+PHP+MySQL)

    简介 xff1a 总结在Windows环境搭建PHP开发环境 xff08 Apache 43 PHP 43 MySQL xff09 安装Apache 1 下载Apache xff0c 地址 xff1a http www apacheloun
  • Java读取Excel文件

    简介 xff1a 总结Java读取Excel文件 添加maven依赖 lt dependency gt lt groupId gt org apache poi lt groupId gt lt artifactId gt poi ooxm
  • 【python】Pytest+Request+Allure+Jenkins 接口自动化测试Demo

    摘要 xff1a 用postman的一个接口为例子 xff0c 做了一个接口自动化测试 xff0c 使用Pytest 43 Request 43 Allure 43 Jenkins 框架 xff0c 现在加以总结 技术栈 xff1a pyt
  • windows django生产用

    mod wsgi 下载 注意 xff1a 下载mod wsgi so版本需和python和apache匹配 http www lfd uci edu gohlke pythonlibs mod wsgi 我之前下过一个对应apache22和
  • 2021-02-19

    升级从版本5 5到6 x的VMware ESXi 转自 xff1a https www cisco com c zh cn support docs servers unified computing vmware esxi cisco u
  • zabbix 5.4在 CentOS8.3中的安装(mysql8/php7)

    0x1 安装 zabbix包及各种必用软件和依赖 rpm Uvh https repo zabbix com zabbix 5 4 rhel 8 x86 64 zabbix release 5 4 1 el8 noarch rpm dnf
  • win32 编程中,在调试窗口中显示内容的方法

    void myprintf string x TCHAR a 64 sprintf s a 34 这是方向 xff1a s n 34 x OutputDebugString a
  • win32下 多线程(多一个线程)GDI 坦克大战

    一个字 累并快乐 xff0c 兴趣索然 追回梦想 学习WINDOWS编程2个月 下一步 xff1a DIrectX9 自己加载资源 xff1a 素材在下面自行下载 xff08 修改成BMP格式 xff09 resource h NO DEP