Bagaimana cara menaikkan variabel tanpa melebihi nilai maksimum?


89

Saya sedang mengerjakan program video game sederhana untuk sekolah dan saya telah membuat metode di mana pemain mendapat 15 poin kesehatan jika metode itu dipanggil. Saya harus menjaga kesehatan pada maksimal 100 dan dengan kemampuan pemrograman saya yang terbatas pada saat ini saya melakukan sesuatu seperti ini.

public void getHealed(){
    if(health <= 85)
        health += 15;
    else if(health == 86)
        health += 14;
    else if(health == 87)
    health += 13; 
}// this would continue so that I would never go over 100

Saya mengerti sintaks saya tentang tidak sempurna tetapi pertanyaan saya adalah, cara apa yang lebih baik untuk melakukannya, karena saya juga harus melakukan hal serupa dengan titik kerusakan dan tidak berada di bawah 0.

Ini disebut aritmatika saturasi .


7
Sebagai catatan tambahan, saya akan memilih nama yang berbeda untuk metode ini. Sesuai standar Java (dan sebagian besar bahasa lain yang saya ketahui), nama metode yang dimulai dengan "get" harus mengembalikan nilai, dan tidak mengubah apa pun. Demikian juga nama metode yang dimulai dengan "set" harus mengubah nilai dan biasanya tidak mengembalikan apa pun.
Darrel Hoffman

Jawaban:


226

Saya hanya akan melakukan ini. Ini pada dasarnya membutuhkan minimum antara 100 (kesehatan maksimal) dan seperti apa kesehatan dengan 15 poin tambahan. Ini memastikan bahwa kesehatan pengguna tidak melebihi 100.

public void getHealed() {
    health = Math.min(health + 15, 100);
}

Untuk memastikan bahwa hitpoints tidak turun di bawah nol, Anda dapat menggunakan fungsi yang sama: Math.max.

public void takeDamage(int damage) {
    if(damage > 0) {
        health = Math.max(health - damage, 0);
    }
}

71

tambahkan saja 15 ke kesehatan, jadi:

health += 15;
if(health > 100){
    health = 100;
}

Namun, seperti yang dicatat oleh hambar, terkadang dengan multi-threading (beberapa blok kode yang dijalankan sekaligus) memiliki kesehatan melebihi 100 pada titik mana pun dapat menyebabkan masalah, dan mengubah properti kesehatan beberapa kali juga bisa berdampak buruk. Dalam hal ini, Anda dapat melakukan ini, seperti yang disebutkan dalam jawaban lain.

if(health + 15 > 100) {
    health = 100;
} else {
    health += 15;
}

9
Jika tidak dibiarkan, hal ini dapat menimbulkan masalah baru seperti kondisi balapan di mana kesehatan karakter diasumsikan paling banyak maksimal kesehatan yang ditentukan (100). Tidak mungkin untuk proyek tingkat ini, saya kira tetapi harus menerapkan praktik yang baik sejak awal.
hambar

6
@bland Jika seseorang menggunakan pendekatan ini, cara untuk menghindari kondisi balapan seperti itu adalah dengan menggunakan variabel sementara untuk menyimpan nilai kesehatan baru, dan kemudian menyetel kesehatan ke nilai kesehatan baru ini di satu tempat, dengan sinkronisasi jika perlu.
Bob

13
@bland: Kondisi balapan hanya relevan saat multi-threading. Dan jika dia melakukan multi-threading (yang saya sangat meragukan) , solusinya adalah mengunci semua akses health, atau memastikan healthhanya diakses dari satu utas. Batasan "Tidak boleh membiarkan kesehatan melebihi 100" bukanlah hal yang realistis.
BlueRaja - Danny Pflughoeft

@ BlueRaja-DannyPflughoeft Saya menyatakan itu tidak mungkin untuk proyek ini. Secara umum kunci tidak akan selalu digunakan dan jika Anda memiliki nilai maksimal maka kunci itu harus ditaati dengan ketat, bermain game atau sebaliknya. Contoh: Jika sebuah peristiwa terkait dengan perubahan properti, dan menggunakan persentase, maka Anda sekarang sangat memiringkan pemrosesan itu, serta memintanya dipanggil dua kali. Saya mencoba untuk tetap umum di sini dan memastikan OP belajar - Saya merasa jawaban ini, meskipun berhasil, terlalu sempit dan spesifik untuk seorang siswa karena akan memaksanya untuk tidak memikirkan gambaran besarnya.
hambar

@Bob saya pikir itu tidak perlu untuk sesuatu yang sederhana ini.
Math chiller

45

Anda tidak memerlukan kasing terpisah untuk setiap kasus di intatas 85. Cuma punya satu else, biar kalo kesehatannya udah 86atau lebih tinggi ya langsung set saja ke 100.

if(health <= 85)
    health += 15;
else
    health = 100;

25
Sedikit terlalu banyak angka ajaib bagi saya (bahkan mengingat 100 diperbolehkan) - ketika mengubah 15 menjadi 16 angka 85 perlu disesuaikan. Bukankah mengubah 85 menjadi setidaknya 100 - 15(atau 100 -HEALED_HEALTH) menjadi perbaikan?
Maciej Piechotka

37

Saya pikir cara idiomatik, berorientasi objek untuk melakukan ini adalah dengan memiliki setHealthdi Characterkelas. Implementasi metode itu akan terlihat seperti ini:

public void setHealth(int newValue) {
    health = Math.max(0, Math.min(100, newValue))
}

Ini mencegah kesehatan turun di bawah 0 atau lebih tinggi dari 100, terlepas dari apa yang Anda atur.


getHealed()Penerapan Anda bisa saja seperti ini:

public void getHealed() {
    setHealth(getHealth() + 15);
}

Apakah masuk akal jika metode Characterto have-a getHealed()adalah latihan yang diserahkan kepada pembaca :)


5
+1: Ini adalah cara yang bagus untuk melakukan ini dengan cara berorientasi objek! Satu-satunya hal yang mungkin saya sarankan (dan ini mungkin akan diserahkan kepada pembaca) adalah mungkin memiliki dua metode ( heal(int hp)dan damage(int hp)) yang masing-masing memanggil setHealth(int newValue)metode Anda .
Chris Forrence

18
Apa yang salah dengan memanggil fungsi perpustakaan? Seperti fungsi bernama, mereka mengekspresikan maksud lebih jelas daripada sekumpulan logika bersyarat.
erickson

2
Juga banyak fungsi perpustakaan (dan kemungkinan besar yang satu ini) benar-benar built-in dan tidak akan melakukan panggilan sama sekali.
kriss

2
@Matteo Jawaban salah - kemungkinan besar fungsi perpustakaan melakukan hal yang persis sama secara internal, jadi mengapa mengulanginya sendiri dan mencemari kode Anda? TIDAK menggunakan fungsi perpustakaan tidak mengikuti prinsip dasar KERING.
NickG

2
@Matteo ini bukan untuk menghindari if. Ini untuk mencegah diri Anda menembak diri sendiri di kaki. Jika terlalu bertele-tele, cukup gunakan impor statis. Maka akan terlihat seperti ini: health = max(0, min(100, newValue)) Jika itu masih belum terbaca oleh Anda, ekstrak ke metode bernama clampsehingga barisnya terlihat seperti ini:health = clamp(0, 100, newValue)
Daniel Kaplan

14

Saya hanya akan menawarkan potongan kode yang lebih dapat digunakan kembali, ini bukan yang terkecil tetapi Anda dapat menggunakannya dengan jumlah berapa pun sehingga masih layak untuk dikatakan

health += amountToHeal;
if (health >= 100) 
{ 
    health = 100;
}

Anda juga dapat mengubah 100 menjadi variabel maxHealth jika Anda ingin menambahkan statistik ke permainan yang Anda buat, sehingga seluruh metode bisa menjadi seperti ini

private int maxHealth = 100;
public void heal(int amountToHeal)
{
    health += amountToHeal;
    if (health >= maxHealth) 
    { 
        health = maxHealth;
    }
}

EDIT

Untuk informasi tambahan

Anda dapat melakukan hal yang sama ketika pemain mengalami kerusakan, tetapi Anda tidak memerlukan minHealth karena itu akan menjadi 0. Melakukannya dengan cara ini Anda akan dapat merusak dan menyembuhkan jumlah berapa pun dengan kode yang sama.


1
minHealthmungkin negatif, katakanlah misalnya, di D & D ... :)
JYelton

1
Sejauh ini jawaban terbaik di sini.
Glitch Desire

@JYelton, ya Anda baru saja mengatakan (kesehatan <= 0) di pernyataan if. Anda dapat menanganinya sesuka Anda, jika Anda ingin mereka memiliki nyawa Anda hanya minus 1 dari lifeCount atau hanya jika mereka benar-benar kalah maka itu dapat mengatasinya. Jika Anda mau, Anda bahkan dapat membuat mereka memulai hidup baru dengan jumlah -HP yang mereka miliki. Anda dapat menempelkan kode ini di hampir semua tempat dan itu akan berfungsi dengan baik, itulah inti dari jawaban ini.
5tar-Kaster

10
health = health < 85 ? health + 15 : 100;

4

Saya akan membuat metode statis di kelas pembantu. Dengan cara ini, daripada mengulang kode untuk setiap nilai yang harus sesuai dengan beberapa batasan, Anda dapat memiliki satu metode serbaguna. Ini akan menerima dua nilai yang mendefinisikan min dan max, dan nilai ketiga untuk dijepit dalam kisaran itu.

class HelperClass
{
    // Some other methods

    public static int clamp( int min, int max, int value )
    {
        if( value > max )
            return max;
        else if( value < min )
            return min;
        else
            return value;
    }
}

Untuk kasus Anda, Anda akan menyatakan kesehatan minimum dan maksimum Anda di suatu tempat.

final int HealthMin = 0;
final int HealthMax = 100;

Kemudian panggil fungsi yang meneruskan kesehatan min, maks, dan yang disesuaikan.

health = HelperClass.clamp( HealthMin, HealthMax, health + 15 );

3

Saya tahu ini adalah proyek sekolah, tetapi jika Anda ingin mengembangkan game Anda nanti dan dapat meningkatkan kekuatan penyembuhan Anda, tulis fungsinya seperti ini:

public void getHealed(healthPWR) {
    health = Math.min(health + healthPWR, 100);
}

dan panggil fungsinya:

getHealed(15);
getHealed(25);

... dll ...

Selanjutnya Anda dapat membuat HP maks Anda dengan membuat variabel yang tidak sesuai dengan fungsi. Karena saya tidak tahu bahasa apa yang Anda gunakan, saya tidak akan menampilkan contoh karena mungkin sintaksnya salah.


2

Mungkin ini?

public void getHealed()
{
  if (health <= 85)
  {
    health += 15;
  } else
  {
    health = 100;
  }
}

2

Jika Anda ingin menjadi kurang ajar dan memasukkan kode Anda dalam satu baris, Anda dapat menggunakan operator terner :

health += (health <= 85) ? 15 : (100 - health);

Perhatikan bahwa beberapa orang tidak menyukai sintaks ini karena (bisa dibilang) keterbacaan yang buruk!


4
Saya menemukan health = (health <= 85)?(health+15):100lebih mudah dibaca (jika Anda benar-benar ingin menggunakan operator terner)
Matteo

1

Saya yakin ini akan berhasil

if (health >= 85) health = 100;
else health += 15;

Penjelasan:

  • Jika celah untuk penyembuhan 15 atau kurang, kesehatan akan menjadi 100.

  • Jika tidak, jika jaraknya lebih besar dari 15, itu akan menambah 15 kesehatan.

Jadi misalnya: jika kesehatannya 83, itu akan menjadi 98 tetapi bukan 100.


Dapatkah Anda menjelaskan cara kerjanya untuk menyelesaikan pertanyaan pemohon?
Ro Yo Mi

Jika gap untuk penyembuhan 15 atau kurang kesehatan akan menjadi 100 lagi jika kesenjangan lebih besar dari 15 itu akan menambah 15 kesehatan. jadi untuk Contoh kesehatan adalah 83 akan menjadi 98 tetapi bukan 100. Jika ada perhatian khusus tolong beritahu saya, terima kasih atas komentarnya.
MarmiK

The && health < 100kondisi tidak diperlukan. Jika 100, maka akan disetel ke 100, tidak ada perubahan. Satu-satunya alasan Anda membutuhkannya adalah jika mungkin untuk mendapatkan> 100 entah bagaimana dan kami tidak ingin penyembuhan mengurangi Anda kembali ke 100.
Darrel Hoffman

@DarrelHoffman Saya pikir Anda benar jika permainan tidak memberikan kesehatan ekstra 100+ maka Anda benar, saya telah mengoreksi jawaban saya :) terima kasih
MarmiK

1

Jika saya ingin thread safe, saya akan melakukannya dengan cara ini daripada menggunakan blok tersinkronisasi.

Perbandingan atomik mencapai hasil yang sama seperti yang disinkronkan tanpa overhead.

AtomicInteger health = new AtomicInteger();

public void addHealth(int value)
{
    int original = 0;
    int newValue = 0;
    do
    {
        original = health.get();
        newValue = Math.min(100, original + value);
    }
    while (!health.compareAndSet(original, newValue));
}

1

Cara paling sederhana menggunakan operator modulus.

kesehatan = (kesehatan + 50)% 100;

kesehatan tidak akan pernah sama atau melebihi 100.


Tetapi jika Anda melakukan operasi itu saat healthberusia 100 tahun, Anda akan berakhir dengan 50 kesehatan.
Parziphal

0
   private int health;
    public void Heal()
    {
        if (health > 85)
            health = 100;
        else
            health += 15;
    }
    public void Damage()
    {
        if (health < 15)
            health = 0;
        else
            health -= 15;
    }

jika Anda akan membuat fungsi, Anda setidaknya harus membuat 15 menjadi parameter :)
Jordan

@ Jordan: Itu tergantung pada konteks saya menulis kode. :-)
cium ketiak saya
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.