<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
<style>
* {
padding: 0;
margin: 0;
text-align: center;
vertical-align: middle;
}
</style>
</head> <body>
<canvas id="one-two">此浏览器可能不支持canvas</canvas>
</body>
<script type="text/javascript" charset="utf-8">
class OneTwo {
constructor(canvasId) {
this.rowCount = 3;
this.colCount = this.rowCount;
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext("2d");
this.cellWidth = 100; // 单位px this.offsetX = this.cellWidth / 2;
this.offsetY = this.offsetX;
this.width = this.cellWidth * this.rowCount + this.offsetX * 2;
this.height = this.width;
this.canvasId = canvasId; this.pieces = [];
this.active = 2; //
this.status = 1; // 1添加子 2移动子
this.R = this.cellWidth * 0.3;
this.hint = []; // 提示位置
this.toMove = {}; // 即将移动的棋子 this.init();
} // 渲染页面
renderUi() {
//清除之前的画布
this.ctx.clearRect(0, 0, this.width, this.height); // 重绘画布
this.drawMap();
this.drawPieces();
console.log(this.toMove, "渲染前选择的棋子")
this.highLight();
} //初始化
init() {
this.initCanvas();
this.drawMap();
this.initPieces();
} //
initCanvas() {
this.canvas.width = this.width;
this.canvas.height = this.height;
} // initPieces(){}
initPieces() {
for(let i = 0; i <= this.rowCount; i++) {
this.pieces[i] = [];
for(let j = 0; j <= this.colCount; j++) {
this.pieces[i][j] = 0;
}
}
console.log(this.pieces);
} // 画地图
drawMap() {
// 背景
this.ctx.beginPath();
this.ctx.rect(0, 0, this.width, this.height);
this.ctx.closePath();
this.ctx.fillStyle = "#0099CC";
this.ctx.fill(); // 画横线
this.ctx.strokeStyle = "black";
this.ctx.beginPath();
for(let i = 0; i <= this.rowCount; i++) {
this.ctx.moveTo(0 + this.offsetX, this.cellWidth * i + this.offsetY);
this.ctx.lineTo(this.cellWidth * this.rowCount + this.offsetX, this.cellWidth * i + this.offsetY);
}
this.ctx.stroke(); // 画纵线
this.ctx.beginPath();
for(let i = 0; i <= this.colCount; i++) {
this.ctx.moveTo(this.cellWidth * i + this.offsetX, 0 + this.offsetY);
this.ctx.lineTo(this.cellWidth * i + this.offsetX, this.cellWidth * this.colCount + this.offsetY);
}
this.ctx.stroke();
} //画一个棋子或一个提示圆点
drawDot(x, y, r, color) {
this.ctx.beginPath();
this.ctx.arc(x, y, r, 0, 2 * Math.PI);
this.ctx.closePath(); this.ctx.fillStyle = color;
this.ctx.fill();
} // 画所有的棋子
drawPieces() {
//console.log(this.pieces)
for(var i = 0; i < this.pieces.length; i++) {
for(let j = 0; j < this.pieces[i].length; j++) {
if(this.pieces[i][j] !== 0) {
this.drawOnePiece(i, j, this.R, this.getColor(this.pieces[i][j]));
}
}
}
} //
drawOnePiece(i, j, r, color) {
var x = i * this.cellWidth + this.offsetX;
var y = j * this.cellWidth + this.offsetY;
this.drawDot(x, y, r, color);
} // 获取某个棋子的颜色 0——空 1——白 2——黑
getColor(num) {
var res = "";
switch(num) {
case 0:
res = "";
break;
case 2:
res = "black";
break;
case 1:
res = "white";
break;
case -1:
res = "yellow";
break;
default:
res = "red"; // 错误了
}
return res;
} // cango
canGo(x, y) {
if(this.pieces[x][y] == 0) {
return true;
} else {
return false;
}
} // 添加棋
add(x, y) {
if(this.canGo(x, y)) {
this.pieces[x][y] = this.active;
// this.drawOnePiece(x,y);
this.weed(x, y);
this.renderUi();
this.exchange();
console.log(this.pieces, "当前棋局")
} else {
console.warn("这里貌似不能添加棋子");
}
} // 是否可以移动
oneCanMove(x, y, oneSide) {
var moveRange = this.getMoveRange(x, y, oneSide);
if(moveRange.length) {
return true;
} else {
return false;
}
}
// 所有的棋子是否可以移动
hasCanMovePiece(oneSide) {
var oneSideCanMove = false;
for(let i = 0, len = this.pieces.length; i < len; i++) {
for(let j = 0, len1 = this.pieces[i].length; j < len1; j++) {
if(this.pieces[i][j] === oneSide) {
if(this.oneCanMove(i, j, oneSide)) {
oneSideCanMove = true;
break;
}
}
}
}
return oneSideCanMove;
} // 获取某一方的棋子数量
getCount(oneSide) {
var count = 0;
for(let i = 0, len = this.pieces.length; i < len; i++) {
for(let j = 0, len1 = this.pieces[i].length; j < len1; j++) {
if(this.pieces[i][j] === oneSide) {
count++;
}
}
}
return count;
} // 没有棋走,自己拔出自己的一颗子
weedOne(x, y) {
this.pieces[x][y] = 0;
} // 转换状态从添加棋子到移动棋子
changeStatus() {
console.log("状态转换了");
this.status = 2;
}
// 当棋盘下满的时候转换状态。下满的时候黑方+白方的总数等于16
wetherChangeStatus() {
console.log("判断是否要转换状态", this.getCount(1) + this.getCount(2))
if(this.getCount(1) + this.getCount(2) == 16) {
return true;
} else {
return false;
}
} // 切换角色(换着走棋)
exchange() {
this.active = this.active == 1 ? 2 : 1;
} // 获取敌方数字
getEnemy(oneSide) {
return oneSide == 1 ? 2 : 1;
} // 选择移动的棋子
chooseToMove(x, y, oneSide) {
if(this.oneCanMove(x, y, oneSide)) {
this.toMove.x = x;
this.toMove.y = y;
//this.highLight();
} else {
delete this.toMove.x;
delete this.toMove.y;
console.warn("这个棋子不可以移动");
}
console.log(this.toMove, "选择后的要移动的棋子")
} // 判断移动的最终位置是否在移动范围内
inRange(x, y, oneSide) {
var moveRange = this.getMoveRange(this.toMove.x, this.toMove.y, oneSide);
console.log(moveRange, "移动范围");
var flag = false;
for(let i = 0, len = moveRange.length; i < len; i++) {
if(x == moveRange[i].x && y == moveRange[i].y) {
flag = true;
break;
}
}
return flag;
} // 移动 1.选择需要移动的棋子 2.点击推荐的可以移动的位置 3.之前的位置赋值为空,结束的位置赋值为当前棋子
move(x, y) {
if(Object.keys(this.toMove).length) { // 已经选了将要移动的棋子 移动
if(this.pieces[x][y] == this.active) { // 这时候想移动别的棋子
console.log("重新选择要移动的棋子x:" + x + ";y:" + y);
this.chooseToMove(x, y, this.active);
//this.renderUi();
} else {
if(this.inRange(x, y, this.active)) { // 移动当前棋子 删除己选择的移动棋子 去除已选择状态
console.log("移动棋子");
this.pieces[x][y] = this.active;
this.pieces[this.toMove.x][this.toMove.y] = 0;
this.weed(x, y); this.exchange();
delete this.toMove.x;
delete this.toMove.y;
//this.renderUi(); } else {
console.log("移动范围超标了,每次只可以横向或纵向移动一格");
}
}
} else { // 选择要移动的棋子
console.log("选择要移动的棋子x:" + x + ";y:" + y);
this.chooseToMove(x, y, this.active);
//this.renderUi();
} this.renderUi();
} // goStep
goStep(x, y) {
if(this.status == 1) { // 添加
this.add(x, y);
if(this.wetherChangeStatus()) {
this.changeStatus();
}
} else { // 拔子 移动
if(this.hasCanMovePiece(this.active)) { // 移动
console.log("移动主流程");
this.move(x, y);
this.getVictor();
} else { //拔子
console.log("拔子主流程");
if(this.pieces[x][y] == this.active) {
this.weedOne(x, y);
this.exchange();
this.renderUi();
this.getVictor();
} else {
console.log("子不是你的,拔个锤子");
}
}
}
} // 给选择的棋子加上高亮标记
highLight() {
console.log(this.toMove);
if(!Object.keys(this.toMove).length) {
return;
}
console.log("要开始画了")
var x = this.toMove.x;
var y = this.toMove.y;
var pArr = ["lt", "ld", "rd", "rt"];
for(let i = 0, len = pArr.length; i < len; i++) {
var xx = x * this.cellWidth + this.offsetX;
var yy = y * this.cellWidth + this.offsetY;
this.drawRightAngle(xx, yy, this.R, 10, pArr[i]);
}
} // 画直角 以圆心为起点,2r为边的正方形的角,length为画的线的长度,p为需要画的角(如:左上角lt)
drawRightAngle(x, y, r, length, p, color) {
color = color || "yellow";
var nd = this.nd(p);
var h = nd.h;
var v = nd.v;
this.ctx.beginPath();
this.ctx.strokeStyle = color;
this.ctx.moveTo(x + h * r, y + v * r);
this.ctx.lineTo(x + h * r - h * length, y + v * r);
this.ctx.moveTo(x + h * r, y + v * r);
this.ctx.lineTo(x + h * r, y + v * r - v * length);
this.ctx.closePath();
this.ctx.stroke();
} // 显示提示位置 // 显示移动范围
getMoveRange(x, y, oneSide) {
var moveRange = [];
if(this.pieces[x][y] === oneSide) {
var dArr = ["r", "d", "l", "t"];
var direction, h, v;
for(let i = 0, len = dArr.length; i < len; i++) {
direction = this.nd(dArr[i]);
h = direction.h;
v = direction.v;
if(this.pieces[x + h] && this.pieces[x + h][y + v] === 0) {
moveRange.push({
x: x + h,
y: y + v
});
}
}
} else {
console.log("空位置和敌方的棋子不可以移动,请移动自己的棋子到空位置");
}
return moveRange;
} // 获取赢家
getVictor() {
var white = this.getCount(1);
var black = this.getCount(2);
if(white == 0) {
setTimeout(() => {
alert("黑棋赢咧");
}, 50);
} else if(black == 0) {
setTimeout(() => {
alert("白棋赢咧");
}, 50);
}
} // 拔子
weed(x, y) {
var dArr = ["r", "d", "l", "t"];
var direction, h, v, np;
for(let i = 0, len = dArr.length; i < len; i++) {
direction = this.nd(dArr[i]);
h = direction.h;
v = direction.v;
np = this.np(x, y, dArr[i]);
// 先看自己有没有凑够两个子,凑够了才可以吃子
if(np === 0) {
if(this.pieces[x + h] && this.pieces[x + h][y + v] === this.active) { //AA??
if(this.pieces[x + 2 * h] && this.pieces[x + 2 * h][y + 2 * v] === this.getEnemy(this.active)) { //AAB?
if(this.pieces[x + 3 * h] && this.pieces[x + 3 * h][y + 3 * v] === this.getEnemy(this.active)) { //AABB
this.pieces[x + 2 * h][y + 2 * v] = 0;
this.pieces[x + 3 * h][y + 3 * v] = 0;
} else if(this.pieces[x + 3 * h] && this.pieces[x + 3 * h][y + 3 * v] === this.active) { //AABA
continue;
} else { // AABO
this.pieces[x + 2 * h][y + 2 * v] = 0;
}
} else { // AAA? 或AAO?
continue;
}
} else { //AB??或AO??
continue;
}
} else if(np === 1) {
if(this.pieces[x + h] && this.pieces[x + h][y + v] === this.active) { //?AA?
if(this.pieces[x - h] && this.pieces[x - h][y - v] === this.getEnemy(this.active)) { //BAA?
if(this.pieces[x + 2 * h] && this.pieces[x + 2 * h][y + 2 * v] === this.getEnemy(this.active)) { //BAAB
continue;
} else if(this.pieces[x + 2 * h] && this.pieces[x + 2 * h][y + 2 * v] === this.active) { //BAAA
continue;
} else { //BAAO
this.pieces[x - h][y - v] = 0;
}
} else if(this.pieces[x - h] && this.pieces[x - h][y - v] === this.active) { // AAA?
continue;
} else { //OAA?
if(this.pieces[x + 2 * h] && this.pieces[x + 2 * h][y + 2 * v] === this.getEnemy(this.active)) {
this.pieces[x + 2 * h][y + 2 * v] = 0;
} else {
continue;
}
}
} else if(this.pieces[x + h] && this.pieces[x + h][y + v] === this.getEnemy(this.active)) { //?AB?
if(this.pieces[x - h] && this.pieces[x - h][y - v] === this.active) { //AAB?
if(this.pieces[x + 2 * h] && this.pieces[x + 2 * h][y + 2 * v] === this.getEnemy(this.active)) { //AABB
this.pieces[x + h][y + v] = 0;
this.pieces[x + 2 * h][y + 2 * v] = 0;
} else if(this.pieces[x + 2 * h] && this.pieces[x + 2 * h][y + 2 * v] === this.active) { //AABA
continue;
} else { //AABO
this.pieces[x + h][y + v] = 0;
}
} else { //OAB? BAB?
continue;
}
} else { //?AO?
continue;
}
} else if(np === 2) {
if(this.pieces[x + h] && this.pieces[x + h][y + v] === this.active) { //??AA
if(this.pieces[x - h] && this.pieces[x - h][y - v] === this.getEnemy(this.active)) { //?BAA
if(this.pieces[x - 2 * h] && this.pieces[x - 2 * h][y - 2 * v] === this.getEnemy(this.active)) { //BBAA
this.pieces[x - 2 * h][y - 2 * v] = 0;
this.pieces[x - h][y - v] = 0;
} else if(this.pieces[x - 2 * h] && this.pieces[x - 2 * h][y - 2 * v] === this.active) { //ABAA
continue;
} else { //OBAA
this.pieces[x - h][y - v] = 0;
}
} else { // ?OAA 或?AAA
continue;
}
} else if(this.pieces[x + h] && this.pieces[x + h][y + v] === this.getEnemy(this.active)) { //??AB
if(this.pieces[x - h] && this.pieces[x - h][y - v] === this.active) { //?AAB
if(this.pieces[x - 2 * h] && this.pieces[x - 2 * h][y - 2 * v] === this.getEnemy(this.active)) { //BAAB
// this.pieces[x-h][y-v] = 0;
// this.pieces[x-2*h][y-2*v] = 0;
continue;
} else if(this.pieces[x - 2 * h] && this.pieces[x - 2 * h][y - 2 * v] === this.active) { //AAAB
continue;
} else { //OAAB
this.pieces[x + h][y + v] = 0;
}
} else { //?BAB或?OAB
continue;
}
} else { //??AO
if(this.pieces[x - h] && this.pieces[x - h][y - v] === this.active) { //?AAO
if(this.pieces[x - 2 * h] && this.pieces[x - 2 * h][y - 2 * v] === this.getEnemy(this.active)) { //BAAO
this.pieces[x - 2 * h][y - 2 * v] = 0;
} else { //AAAO或OAAO
continue;
}
} else { //?BAO 或?OAO
continue;
}
}
} else if(np === 3) {
if(this.pieces[x - h] && this.pieces[x - h][y - v] === this.active) { //??AA
if(this.pieces[x - 2 * h] && this.pieces[x - 2 * h][y - 2 * v] === this.getEnemy(this.active)) { //?BAA
if(this.pieces[x - 3 * h] && this.pieces[x - 3 * h][y - 3 * v] === this.getEnemy(this.active)) { //BBAA
this.pieces[x - 2 * h][y - 2 * v] = 0;
this.pieces[x - 3 * h][y - 3 * v] = 0;
} else if(this.pieces[x - 3 * h] && this.pieces[x - 3 * h][y - 3 * v] === this.active) { //ABAA
continue;
} else { // OBAA
this.pieces[x - 2 * h][y - 2 * v] = 0;
}
} else { // ?AAA 或?OAA
continue;
}
} else { //??BA或??OA
continue;
}
}
}
} // 方向数字化numberDirection r(1,0) rd(1,1) ld(-1,1)
nd(direction) {
var res = {
h: 0,
v: 0
}; // h horizontal v vertical
switch(direction) {
case "r":
res.h = 1;
res.v = 0;
break;
case "rd":
res.h = 1;
res.v = 1;
break;
case "d":
res.h = 0;
res.v = 1;
break;
case "ld":
res.h = -1;
res.v = 1;
break;
case "l":
res.h = -1;
res.v = 0;
break;
case "lt":
res.h = -1;
res.v = -1;
break;
case "t":
res.h = 0;
res.v = -1;
break;
case "rt":
res.h = 1;
res.v = -1;
break;
default:
console.error("方向输入有误");
}
return res;
} // 某个方向上当前(x,y)是第几个位置
np(x, y, direction) {
var d = this.nd(direction);
if(d.h !== 0) {
if(d.h === 1) {
return x;
} else { // -1
return 3 - x;
}
} else {
if(d.v === 1) {
return y;
} else { //-1
return 3 - y;
}
}
console.error("np出错了");
return 0;
} // 深拷贝
deepClone(values) {
var copy; // Handle the 3 simple types, and null or undefined
if(null == values || "object" != typeof values) return values; // Handle Date
if(values instanceof Date) {
copy = new Date();
copy.setTime(values.getTime());
return copy;
} // Handle Array
if(values instanceof Array) {
copy = [];
for(var i = 0, len = values.length; i < len; i++) {
copy[i] = this.deepClone(values[i]);
}
return copy;
} // Handle Object
if(values instanceof Object) {
copy = {};
for(var attr in values) {
if(values.hasOwnProperty(attr)) copy[attr] = this.deepClone(values[attr]);
}
return copy;
} throw new Error("Unable to copy values! Its type isn't supported.");
}
}
</script>
<script type="text/javascript">
var oneTwo = new OneTwo("one-two");
var canvas = document.getElementById("one-two");
console.log(canvas.getBoundingClientRect());
var offset;
canvas.addEventListener("click", function(e) {
offset = canvas.getBoundingClientRect();
var x = Math.floor((e.clientX - offset.left) / oneTwo.cellWidth);
var y = Math.floor((e.clientY - offset.top) / oneTwo.cellWidth);
console.log(x, y, "点击位置"); // 走棋
oneTwo.goStep(x, y);
}, false);
</script> </html>

玩法简介:

1. 一只一担是流传在中国米黄玉之乡的谭山镇的一种双人、益智、棋牌类游戏。棋盘是4*4的方格线,棋子放在线与线的交界处。棋子可以用任意两种可以区分的道具,如纸团、石子、木棍等。因此随时随地,只要在地上画个4*4的方格,弄几个石子什么的就可以玩了,非常的方便。

这个游戏分为两个阶段——谋篇布阵和征战。

刚开始,双方在棋盘上抢占有利位置,并互相征战。棋盘上位置占满后,一方弃掉自己的一个子,棋盘上就有空位置了,双方就开始交替移动棋子,进行征战,没有可以移动的棋子时,弃掉自己的一个棋子,轮到对方走棋。直到最后一方没有棋子了结束战斗。

吃子规则

两个(一担)可以吃掉对方的一个或者两个(一担)。具体图形如下(A——甲方,B——乙方,O——空位置):

1. AABO——甲由?ABO,在第一个位置走一个棋后变成AABO;或者由A?BO,在第二个位置走一个棋后变成AABO。则第三个位置的乙方棋子被剔除棋盘,变成空位置,再由双方来争夺这个位置。

2.OAAB——甲由OA?B,在第三个位置走一个棋后变成OAAB;或者由O?AB,在第二个位置有一个棋后变成功能OAAB。则第四个位置的乙方棋子被剔除棋盘,变成空位置,再由双方来争夺这个位置。

3. AABB——甲由?ABB,在第一个位置走一个棋后变成AABB;或者由A?BB,在第二个位置有一个棋后变成功能AABB。则第三和第四个位置的乙方棋子都被剔除棋盘,变成空位置,再由双方来争夺这个位置。

其他的情况不可以吃棋。如以下两个图形。

1. AABA

2.AAAB

通常用这两种棋来防守,防止对方吃掉自己的棋子。

赶紧复制以下去玩玩吧~

js+canvas 一只一担小游戏的更多相关文章

  1. canvas写个简单的小游戏

    之前在HTML5 Canvas属性和方法汇总一文中,介绍过Canvas的各种属性以及方法的说明,并列举了自己写的一些Canvas demo,接下来开始写一个简单的小游戏吧,有多简单,这么说吧,代码不到 ...

  2. html5+Canvas实现酷炫的小游戏

    最近除了做业务,也在尝试学习h5和移动端,在这个过程中,学到了很多,利用h5和canvas做了一个爱心鱼的小游戏.点这里去玩一下 PS: 貌似有点闪屏,亲测多刷新两下就好了==.代码在本地跑都不会闪, ...

  3. JS实现别踩白块小游戏

    最近有朋友找我用JS帮忙仿做一个别踩白块的小游戏程序,但他给的源代码较麻烦,而且没有注释,理解起来很无力,我就以自己的想法自己做了这个小游戏,主要是应用JS对DOM和数组的操作. 程序思路:如图:将游 ...

  4. JS高级---案例:贪吃蛇小游戏

    案例:贪吃蛇小游戏 可以玩的小游戏,略复杂,过了2遍,先pass吧 先创建构造函数,再给原型添加方法.分别创建食物,小蛇和游戏对象. 食物,小蛇的横纵坐标,设置最大最小值,运动起来的函数,按上下左右键 ...

  5. 用canvas和原生js写的一个笨鸟先飞的小游戏(暂时只有一个关卡)

    其中一个画布背景是一张图片,还有小鸟,两个管子的图片.暂时不知道怎么附上去就不添加了.这里只有源代码,css和js都是在html写着的,感觉比他们的容易吧,hah <!DOCTYPE html& ...

  6. 用canvas写个接水管小游戏

    声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 过年的十八天假期迷迷糊糊一下子就过去了(LZ还是实习生,鉴于大学最后一个寒假了,所以就多请了好多天假),又要返工上班了.这是年后的第一篇博 ...

  7. js+canvas(H5)实现小球移动小demo

    *canvas提供画布,大小自定义,js得到画布,从画布对象通过getContext('2d')来得到画笔,然后就可以开始画了 代码: <!DOCTYPE html> <html l ...

  8. js中的投掷筛子的小游戏

    代码 <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...

  9. js下载文件方法与原理小分析

    原理:html的a标签,设置dawnload属性后,可以下载href指向的文件. 在js中往往是点击某一个按钮后下载一个文件,并且文件的地址是变化的.因此我们可以动态创建一个a标签,设置好downlo ...

随机推荐

  1. 图片懒加载插件lazyload.js详解

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  2. vim Tab的设置问题

    VIM 中处理 TAB 异常的方便. 键盘上的 TAB 键,与文件中的 TAB 符号一定要区分开,这是两个概念. 显示当前文件中的 Tab /\t 实际上,就是查询 \t 符号. shiftwidth ...

  3. 理解es6箭头函数

    箭头函数知识点很少,但是要理解清楚,不然看代码会很不适应的. 1. 最简单的写法 x => x*x 可以理解为 我的x要被转化为x*x,所以实际相当于下边的这个 function (x){ re ...

  4. DLX

    #include <iostream> #include <cstdlib> #include <cstring> #include <queue> # ...

  5. 直接删除mysql的日志导致mysql无法启动

    --02T08::.750000Z [Warning] [MY-] [Server] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION ...

  6. python实例 输出字符串和数字

    但有趣的是,在javascript里我们会理想当然的将字符串和数字连接,因为是动态语言嘛.但在Python里有点诡异,如下: #! /usr/bin/python a=2 b="test&q ...

  7. 解决git的the remote end hung up问题_百度经验

    使用git更新或提交中途有时出现The remote end hung up unexpectedly的异常,特别是资源库在国外的情况下.此问题可能由网络原因引起. 工具/原料   git 方法/步骤 ...

  8. PHP 学习1.1

    1 链接mysql 数据简单测试 <html><head>  <title></title>  <meta http-equiv="Co ...

  9. Django项目:CRM(客户关系管理系统)--01--01PerfectCRM基本配置ADMIN01

    一.CRM项目需求 二.CRM项目新建 PerfectCRM crm

  10. cf round 482D Kuro and GCD and XOR and SUM

    题意: 开始有个空集合,现在有两种操作: $(1,x)$:给集合加一个数$x$,$x \leq 10^5$; $(2,x,k,s)$:在集合中找一个$a$,满足$a \leq s-x$,而且$k|gc ...