MC插火把(4种方法),总有一种你能理解

luogu P1789

题目描述

话说有一天 linyorson 在“我的世界”开了一个 n \times nn×n 的方阵,现在他有 mm 个火把和 kk 个萤石,分别放在 (x_1, y_1) \sim (x_m, y_m)(x1​,y1​)∼(xm​,ym​) 和 (o_1, p_1) \sim (o_k, p_k)(o1​,p1​)∼(ok​,pk​) 的位置,没有光或没放东西的地方会生成怪物。请问在这个方阵中有几个点会生成怪物?

P.S. 火把的照亮范围是:

    |暗|暗| 光 |暗|暗|
    |暗|光| 光 |光|暗|
    |光|光|火把|光|光|
    |暗|光| 光 |光|暗|
    |暗|暗| 光 |暗|暗|

萤石:

    |光|光| 光 |光|光|
    |光|光| 光 |光|光|
    |光|光|萤石|光|光|
    |光|光| 光 |光|光|
    |光|光| 光 |光|光|

输入格式

输入共 m + k + 1m+k+1 行。
第一行为 n, m, kn,m,k。
第 22 到第 m + 1m+1 行分别是火把的位置 x_i, y_ixi​,yi​。
第 m + 2m+2 到第 m + k + 1m+k+1 行分别是萤石的位置 o_i, p_ioi​,pi​。

注:可能没有萤石,但一定有火把。

输出格式

有几个点会生出怪物。

样例

样例 #1

样例输入 #1

5 1 0
3 3

样例输出 #1

12

说明/提示

数据保证,1 \le n \le 1001≤n≤100,1 \leq m+k \leq 251≤m+k≤25,1 \leq m \leq 251≤m≤25,0 \leq k \leq 50≤k≤5。

题解1

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 105;
int n=0, m, k, x, y, o, p, ans = 0;
//火把照亮的坐标——13个坐标
int dx1[13] = { 2,0,-2,0,1,1,1,0,0,0,-1,-1,-1 },
dy1[13] = { 0,2,0,-2,0,1,-1,1,0,-1,0,1,-1 };
//萤石照亮的坐标——25个坐标
int dx2[25] = { -2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2 },
dy2[25] = { -2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2 };
int main(){
    cin >> n >> m >> k;
    int a[maxn][maxn];
    memset(a, 0, sizeof(a));                //让数组a中的数值全部初始化为0
    //读入火把坐标并找出照亮的位置
    for (int i = 1; i <= m; i++){
        cin >> x >> y;
        for (int j = 0; j < 13; j++)        //火把光照范围13个坐标
            a[x + dx1[j]][y + dy1[j]] = 1;  //记录光照区域,置为1
    }
    //读入萤石坐标并找出照亮的位置
    for (int i = 1; i <= k; i++){
        cin >> o >> p;
        for (int j = 0; j < 25; j++)        //萤石光照范围25个坐标
            a[o + dx2[j]][p + dy2[j]] = 1;  //记录光照区域,置为1
    }
    //遍历输出没有光照的坐标
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (a[i][j] == 0)               //没有光照的地方——当然也不会有火把或者萤石放在这儿!
                ans++;
    cout << ans;
    return 0;
}

题解2

#include <cstdio> 
#include <cmath>
using namespace std;
int n, m, k, a, b, ans;
int s[5005][5005];
bool pd(int x, int y) { //判断是否越界 
    if (x < 1 || y < 1 || x > n || y > n) return 0;
    return 1;
}
int main() {
    scanf("%d%d%d", &n, &m, &k); //读入 
    for (int i = 1; i <= m + k; i++) { //由于计算火把和萤石的步骤很像,所以合并了 
        scanf("%d%d", &a, &b); //读入火把m的坐标 
        for (int x = -2; x <= 2; x++)
            for (int y = -2; y <= 2; y++) //枚举5*5的方阵(通过计算距离) 
                if ((i > m || abs(x) + abs(y) <= 2) && pd(x + a, b + y))
                    //如果是萤石(i > m)或者x与y的坐标差的和不超过2(想一想为什么)并且
                    //没有越界就标记 
                    s[x + a][b + y]++;
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            ans += s[i][j] == 0; //枚举每一个方格,先判断s[i][j]是不是==0(即没有亮光) 
    printf("%d\n", ans); //输出结果 
    return 0;
}

 题解3

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n,m,k,i,j,o,p,q,s,ans=0;
    cin>>n>>m>>k;
    int map[n+5][n+5];
    memset(map,0,sizeof(map));
    for(i=1;i<=m;i++){
        cin>>o>>p;
        map[o+2][p]=1;
        map[o][p+2]=1;
        map[o-2][p]=1;
        map[o][p-2]=1;
        map[o+1][p]=1;
        map[o+1][p+1]=1;
        map[o+1][p-1]=1;
        map[o][p+1]=1;
        map[o][p]=1;
        map[o][p-1]=1;
        map[o-1][p]=1;
        map[o-1][p+1]=1;
        map[o-1][p-1]=1;
    }
    for(i=1;i<=k;i++){
        cin>>q>>s;
        map[q-2][s-2]=1;
        map[q-2][s-1]=1;
        map[q-2][s]=1;
        map[q-2][s+1]=1;
        map[q-2][s+2]=1;
        map[q-1][s-2]=1;
        map[q-1][s-1]=1;
        map[q-1][s]=1;
        map[q-1][s+1]=1;
        map[q-1][s+2]=1;
        map[q][s-2]=1;
        map[q][s-1]=1;
        map[q][s]=1;
        map[q][s+1]=1;
        map[q][s+2]=1;
        map[q+1][s-2]=1;
        map[q+1][s-1]=1;
        map[q+1][s]=1;
        map[q+1][s+1]=1;
        map[q+1][s+2]=1;
        map[q+2][s-2]=1;
        map[q+2][s-1]=1;
        map[q+2][s]=1;
        map[q+2][s+1]=1;
        map[q+2][s+2]=1;
    }
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            if(map[i][j]==0)ans++;
        }
    }
    cout<<ans;
    return 0;
}

 题解4

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<deque>
#include<map>
using namespace std;
int main() {
	int n, m, k;
	scanf("%d%d%d", &n, &m, &k);
	int arr[n][n];
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			arr[i][j] = 0;
	while (m--) {
		int row, col;
		scanf("%d%d", &row, &col);
		row--, col--;
		if (row + 1 <= n - 1 && col + 1 <= n - 1)
			arr[row + 1][col + 1] = 1;
		if (row + 1 <= n - 1 && col - 1 >= 0)
			arr[row + 1][col - 1] = 1;
		if (row - 1 >= 0 && col - 1 >= 0)
			arr[row - 1][col - 1] = 1;
		if (row - 1 >= 0 && col + 1 <= n - 1)
			arr[row - 1][col + 1] = 1;
		for (int i = col - 2; i <= col + 2; i++)
			if (i >= 0 && i <= n - 1)
				arr[row][i] = 1;
		for (int i = row - 2; i <= row + 2; i++)
			if (i >= 0 && i <= n - 1)
				arr[i][col] = 1;
	}
	while (k--) {
		int row, col;
		scanf("%d%d", &row, &col);
		row--, col--;
		for (int i = row - 2; i <= row + 2; i++)
			for (int j = col - 2; j <= col + 2; j++)
				arr[i][j] = 1;
	}
	int count = 0;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if (arr[i][j] == 0)
				count++;
	printf("%d\n", count);
	return 0;
}

仅供参考

<think>好的,我需要帮助用户寻找Minecraft中火把功能的函数或实现方法。用户提到了Mc生存 P1789,可能是指某个特定的件或模组版本?不过先不管这个,先集中精力在火把的功能上。 首先,根据用户提供的引用,特别是引用[2],里面提到在JuicyRaspberryPie件中,可以通过在特定目录下编写Python脚本,并使用@mcpy装饰器或函数名以_mcpy开头来注册命令。这可能是一个关键点,因为用户可能在使用这个件来扩展Minecraft的功能。 接下来,火把的基本逻辑应该包括几个步骤:检测玩家的位置和朝向,确定火把放置的位置,然后调用相应的API来生成方块。例如,当玩家执行某个命令时,获取其坐标,然后根据视线方向或手持火把的状态来判断是否可以放置火把。 引用[1]中提到,PC版Minecraft可以通过F3查看坐标,这可能意味着坐标获取是关键。在模组或件开发中,可能需要通过API来获取玩家的实时坐标。比如在Python脚本中,可能需要调用类似player.getTilePos()的方法。 然后,引用[4]提到了着色器中处理方块ID的部分,这可能与渲染有关,但用户的问题是关于功能实现,所以暂时可以忽略这部分。不过,方块ID(如mc_Entity)可能在放置火把时需要用到,火把的方块ID是50或torch,具体取决于版本。 引用[3]中的VOYAGER智能体能够自动探索Minecraft,可能需要类似的方法来检测周围环境是否适合放置火把,比如检查是否在固体方块的侧面或顶部。 现在,综合这些信息,可能需要编写一个Python函数,使用JuicyRaspberryPie件提供的API,获取玩家位置,计算放置位置,然后调用setBlock方法放置火把。例如,当玩家执行/p place_torch命令时,触发这个函数。 需要注意的细节:放置火把需要满足条件,比如依附的方块是否坚固,周围是否有空间。可能需要先检查目标位置的方块类型,再决定是否可以放置。例如,火把只能放置在固体方块的顶部或侧面。 另外,引用[5]提到季文瀚自学开发,说明即使没有系统学习计算机科学,也能通过件和API实现功能,鼓励用户尝试。 可能的实现步骤: 1. 注册一个命令,如/p place_torch。 2. 获取玩家当前位置和方向。 3. 计算火把应该放置的位置(玩家前方或视线所指的方块)。 4. 检查该位置是否允许放置火把(依附的方块是否合适)。 5. 调用setBlock放置火把方块。 需要处理的问题包括方向计算、碰撞检测、方块类型判断等。可能需要使用Minecraft Pi的API或其他模组提供的接口。 最后,根据用户提供的引用,特别是引用[2],应该指导用户查看example中的示例代码,并按照格式编写函数,使用装饰器或命名规则来注册命令。同时提醒用户火把的方块ID可能因版本而异,需确认正确的ID。</think>在Minecraft中实现火把功能,通常需要通过件开发或脚本调用API实现。以下是基于JuicyRaspberryPie件和Python脚本的实现思路: ### 一、功能实现步骤 1. **获取玩家坐标与朝向** 使用`mc.player.getTilePos()`获取玩家当前位置的三维坐标$ (x,y,z) $,结合`mc.player.getRotation()`获取水平朝向角度$ \theta $[^1][^2]。 2. **计算火把放置位置** 根据玩家朝向角度$ \theta $计算前方方块坐标。例如: $$ x' = x + \lfloor \cos(\theta) \rfloor \\ z' = z + \lfloor \sin(\theta) \rfloor $$ 需将角度转换为弧度制后计算。 3. **验证可放置条件** 火把必须附着在固体方块表面,可通过`mc.getBlock(x', y', z')`检测目标位置是否非空气方块(ID≠0)。 4. **调用方块放置API** 使用`mc.setBlock(x', y', z', block.TORCH.id)`放置火把火把ID为50(不同版本可能有差异)。 ### 二、示例代码 ```python from mcpi.minecraft import Minecraft from mcpi import block @mcpy # 注册为Minecraft命令 def place_torch(): mc = Minecraft.create() pos = mc.player.getTilePos() rotation = mc.player.getRotation() # 计算前方坐标(简化版) dx = round(math.cos(math.radians(rotation))) dz = round(math.sin(math.radians(rotation))) target_pos = (pos.x + dx, pos.y, pos.z + dz) # 检测附着面是否有效 if mc.getBlock(*target_pos) != block.AIR.id: mc.setBlock(target_pos[0], target_pos[1]+1, target_pos[2], block.TORCH.id) ``` ### 三、高级优化方向 1. **视线检测** 使用`mc.player.getDirection()`获取三维方向向量,实现精确的射线投射检测[^3]。 2. **手持物品判断** 通过`mc.player.getHeldItem()`检测是否持有火把时才允许放置。 3. **多版本适配** 不同平台的火把ID可能不同(基岩版/Java版),需做版本判断[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值